public inbox for [email protected]  
help / color / mirror / Atom feed
[PATCH] Add contrib/anyarray: intarray-style operations and indexes for any array type
3+ messages / 2 participants
[nested] [flat]

* [PATCH] Add contrib/anyarray: intarray-style operations and indexes for any array type
@ 2026-05-18 10:17 Влад Медведицков <[email protected]>
  2026-05-20 02:24 ` Re: [PATCH] Add contrib/anyarray: intarray-style operations and indexes for any array type David G. Johnston <[email protected]>
  0 siblings, 1 reply; 3+ messages in thread

From: Влад Медведицков @ 2026-05-18 10:17 UTC (permalink / raw)
  To: [email protected] <[email protected]>

<div><div><div>From e796800a32277a29013354344ede221b89e46c27 Mon Sep 17 00:00:00 2001</div><div>From: Vlad Medveditskov &lt;[email protected]&gt;</div><div>Date: Mon, 18 May 2026 12:50:13 +0300</div><div>Subject: [PATCH] Add contrib/anyarray: intarray-style operations and indexes</div><div> for any array type</div><div> </div><div>This new contrib module generalizes contrib/intarray to arrays of any</div><div>element type with a default btree opclass.  It provides:</div><div> </div><div>* Set-style helpers for anyarray / anyelement: anyarray_sort</div><div>  (with optional asc/desc direction), anyarray_uniq, anyarray_idx,</div><div>  anyarray_subarray (2- and 3-arg), anyarray_icount,</div><div>  anyarray_intersect, anyarray_union, anyarray_union_elem,</div><div>  anyarray_difference, anyarray_difference_elem, plus the</div><div>  corresponding operators #, &amp;, |, - on anyarray and anyelement.</div><div> </div><div>* A textual boolean query type "anyquery" and the operators</div><div>  anyarray @@ anyquery (with commutator anyquery ~~ anyarray).</div><div>  Tokens are stored as text and parsed lazily through the</div><div>  element type's input function at match time, so the same</div><div>  query value can be used against arrays of different element</div><div>  types.</div><div> </div><div>* A signature-based polymorphic GiST opclass "anyarray_gist_ops"</div><div>  on anyarray.  Each indexed array is hashed into a fixed-size</div><div>  bit vector; internal nodes store the bitwise union of their</div><div>  children, with an ALLISTRUE short-circuit when every bit is</div><div>  set.  Signature length is configurable via the siglen</div><div>  reloption (default 252 bytes).</div><div> </div><div>* GIN opclasses for the three element types most commonly</div><div>  requested by users: int8_anyquery_gin_ops,</div><div>  uuid_anyquery_gin_ops and text_anyquery_gin_ops.  They are</div><div>  per-concrete-type because the GIN AM does not propagate</div><div>  fn_expr into extractQuery, so the element type needed to</div><div>  parse anyquery tokens cannot be discovered dynamically.</div><div>  Strategies 1-4 mirror the built-in array_ops; strategy 5</div><div>  is @@.</div><div> </div><div>* doc/src/sgml/anyarray.sgml with descriptions of every</div><div>  function, operator and opclass, plus a usage example.</div><div> </div><div>* Regression test (contrib/anyarray/sql/anyarray.sql,</div><div>  expected/anyarray.out) covering int8, uuid and text inputs,</div><div>  the error paths, and a cross-AM consistency block that</div><div>  asserts seqscan, GiST and GIN return the same row set for</div><div>  seven representative predicates.</div><div>---</div><div> contrib/Makefile                       |   1 +</div><div> contrib/anyarray/.gitignore            |   4 +</div><div> contrib/anyarray/Makefile              |  27 +</div><div> contrib/anyarray/anyarray--1.0.sql     | 336 +++++++++++</div><div> contrib/anyarray/anyarray.c            | 116 ++++</div><div> contrib/anyarray/anyarray.control      |   6 +</div><div> contrib/anyarray/anyarray.h            | 184 ++++++</div><div> contrib/anyarray/anyarray_bool.c       | 664 ++++++++++++++++++++++</div><div> contrib/anyarray/anyarray_gin.c        | 374 +++++++++++++</div><div> contrib/anyarray/anyarray_gist.c       | 742 +++++++++++++++++++++++++</div><div> contrib/anyarray/anyarray_op.c         | 613 ++++++++++++++++++++</div><div> contrib/anyarray/expected/anyarray.out | 727 ++++++++++++++++++++++++</div><div> contrib/anyarray/meson.build           |  38 ++</div><div> contrib/anyarray/sql/anyarray.sql      | 330 +++++++++++</div><div> contrib/meson.build                    |   1 +</div><div> doc/src/sgml/anyarray.sgml             | 482 ++++++++++++++++</div><div> doc/src/sgml/contrib.sgml              |   1 +</div><div> doc/src/sgml/filelist.sgml             |   1 +</div><div> src/test/regress/regression.diffs      |   0</div><div> src/test/regress/regression.out        |   2 +</div><div> src/tools/pgindent/typedefs.list       |   8 +</div><div> 21 files changed, 4657 insertions(+)</div><div> create mode 100644 contrib/anyarray/.gitignore</div><div> create mode 100644 contrib/anyarray/Makefile</div><div> create mode 100644 contrib/anyarray/anyarray--1.0.sql</div><div> create mode 100644 contrib/anyarray/anyarray.c</div><div> create mode 100644 contrib/anyarray/anyarray.control</div><div> create mode 100644 contrib/anyarray/anyarray.h</div><div> create mode 100644 contrib/anyarray/anyarray_bool.c</div><div> create mode 100644 contrib/anyarray/anyarray_gin.c</div><div> create mode 100644 contrib/anyarray/anyarray_gist.c</div><div> create mode 100644 contrib/anyarray/anyarray_op.c</div><div> create mode 100644 contrib/anyarray/expected/anyarray.out</div><div> create mode 100644 contrib/anyarray/meson.build</div><div> create mode 100644 contrib/anyarray/sql/anyarray.sql</div><div> create mode 100644 doc/src/sgml/anyarray.sgml</div><div> create mode 100644 src/test/regress/regression.diffs</div><div> create mode 100644 src/test/regress/regression.out</div><div> </div><div>diff --git a/contrib/Makefile b/contrib/Makefile</div><div>index 7d91fe77db3..b9586cb3a6b 100644</div><div>--- a/contrib/Makefile</div><div>+++ b/contrib/Makefile</div><div>@@ -6,6 +6,7 @@ include $(top_builddir)/src/Makefile.global</div><div> </div><div> SUBDIRS = \</div><div>         amcheck        \</div><div>+        anyarray    \</div><div>         auth_delay    \</div><div>         auto_explain    \</div><div>         basic_archive    \</div><div>diff --git a/contrib/anyarray/.gitignore b/contrib/anyarray/.gitignore</div><div>new file mode 100644</div><div>index 00000000000..5dcb3ff9723</div><div>--- /dev/null</div><div>+++ b/contrib/anyarray/.gitignore</div><div>@@ -0,0 +1,4 @@</div><div>+# Generated subdirectories</div><div>+/log/</div><div>+/results/</div><div>+/tmp_check/</div><div>diff --git a/contrib/anyarray/Makefile b/contrib/anyarray/Makefile</div><div>new file mode 100644</div><div>index 00000000000..d6eb9ae10ad</div><div>--- /dev/null</div><div>+++ b/contrib/anyarray/Makefile</div><div>@@ -0,0 +1,27 @@</div><div>+# contrib/anyarray/Makefile</div><div>+</div><div>+MODULE_big = anyarray</div><div>+OBJS = \</div><div>+    $(WIN32RES) \</div><div>+    anyarray.o \</div><div>+    anyarray_bool.o \</div><div>+    anyarray_gin.o \</div><div>+    anyarray_gist.o \</div><div>+    anyarray_op.o</div><div>+</div><div>+EXTENSION = anyarray</div><div>+DATA = anyarray--1.0.sql</div><div>+PGFILEDESC = "anyarray - operations and indexes for arrays of any type"</div><div>+</div><div>+REGRESS = anyarray</div><div>+</div><div>+ifdef USE_PGXS</div><div>+PG_CONFIG = pg_config</div><div>+PGXS := $(shell $(PG_CONFIG) --pgxs)</div><div>+include $(PGXS)</div><div>+else</div><div>+subdir = contrib/anyarray</div><div>+top_builddir = ../..</div><div>+include $(top_builddir)/src/Makefile.global</div><div>+include $(top_srcdir)/contrib/contrib-global.mk</div><div>+endif</div><div>diff --git a/contrib/anyarray/anyarray--1.0.sql b/contrib/anyarray/anyarray--1.0.sql</div><div>new file mode 100644</div><div>index 00000000000..84bcff34b5b</div><div>--- /dev/null</div><div>+++ b/contrib/anyarray/anyarray--1.0.sql</div><div>@@ -0,0 +1,336 @@</div><div>+/* contrib/anyarray/anyarray--1.0.sql */</div><div>+</div><div>+-- complain if script is sourced in psql, rather than via CREATE EXTENSION</div><div>+\echo Use "CREATE EXTENSION anyarray" to load this file. \quit</div><div>+</div><div>+--</div><div>+-- Set-style operations for arrays of any btree-orderable element type.</div><div>+--</div><div>+</div><div>+CREATE FUNCTION anyarray_sort(anyarray)</div><div>+RETURNS anyarray</div><div>+AS 'MODULE_PATHNAME', 'anyarray_sort'</div><div>+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;</div><div>+</div><div>+CREATE FUNCTION anyarray_sort(anyarray, text)</div><div>+RETURNS anyarray</div><div>+AS 'MODULE_PATHNAME', 'anyarray_sort_dir'</div><div>+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;</div><div>+</div><div>+CREATE FUNCTION anyarray_uniq(anyarray)</div><div>+RETURNS anyarray</div><div>+AS 'MODULE_PATHNAME', 'anyarray_uniq'</div><div>+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;</div><div>+</div><div>+CREATE FUNCTION anyarray_idx(anyarray, anyelement)</div><div>+RETURNS int4</div><div>+AS 'MODULE_PATHNAME', 'anyarray_idx'</div><div>+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;</div><div>+</div><div>+CREATE FUNCTION anyarray_subarray(anyarray, int4, int4)</div><div>+RETURNS anyarray</div><div>+AS 'MODULE_PATHNAME', 'anyarray_subarray'</div><div>+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;</div><div>+</div><div>+CREATE FUNCTION anyarray_subarray(anyarray, int4)</div><div>+RETURNS anyarray</div><div>+AS 'MODULE_PATHNAME', 'anyarray_subarray_to_end'</div><div>+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;</div><div>+</div><div>+CREATE FUNCTION anyarray_icount(anyarray)</div><div>+RETURNS int4</div><div>+AS 'MODULE_PATHNAME', 'anyarray_icount'</div><div>+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;</div><div>+</div><div>+CREATE FUNCTION anyarray_intersect(anyarray, anyarray)</div><div>+RETURNS anyarray</div><div>+AS 'MODULE_PATHNAME', 'anyarray_intersect'</div><div>+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;</div><div>+</div><div>+CREATE FUNCTION anyarray_union(anyarray, anyarray)</div><div>+RETURNS anyarray</div><div>+AS 'MODULE_PATHNAME', 'anyarray_union'</div><div>+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;</div><div>+</div><div>+CREATE FUNCTION anyarray_union_elem(anyarray, anyelement)</div><div>+RETURNS anyarray</div><div>+AS 'MODULE_PATHNAME', 'anyarray_union_elem'</div><div>+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;</div><div>+</div><div>+CREATE FUNCTION anyarray_difference(anyarray, anyarray)</div><div>+RETURNS anyarray</div><div>+AS 'MODULE_PATHNAME', 'anyarray_difference'</div><div>+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;</div><div>+</div><div>+CREATE FUNCTION anyarray_difference_elem(anyarray, anyelement)</div><div>+RETURNS anyarray</div><div>+AS 'MODULE_PATHNAME', 'anyarray_difference_elem'</div><div>+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;</div><div>+</div><div>+--</div><div>+-- Operators</div><div>+--</div><div>+</div><div>+-- Unary prefix # : cardinality (number of elements)</div><div>+CREATE OPERATOR # (</div><div>+    RIGHTARG = anyarray,</div><div>+    PROCEDURE = anyarray_icount</div><div>+);</div><div>+</div><div>+-- array # element : 1-based index of element, or 0 if not found</div><div>+CREATE OPERATOR # (</div><div>+    LEFTARG = anyarray,</div><div>+    RIGHTARG = anyelement,</div><div>+    PROCEDURE = anyarray_idx</div><div>+);</div><div>+</div><div>+-- Set intersection</div><div>+CREATE OPERATOR &amp; (</div><div>+    LEFTARG = anyarray,</div><div>+    RIGHTARG = anyarray,</div><div>+    COMMUTATOR = &amp;,</div><div>+    PROCEDURE = anyarray_intersect</div><div>+);</div><div>+</div><div>+-- Set union (array | array)</div><div>+CREATE OPERATOR | (</div><div>+    LEFTARG = anyarray,</div><div>+    RIGHTARG = anyarray,</div><div>+    COMMUTATOR = |,</div><div>+    PROCEDURE = anyarray_union</div><div>+);</div><div>+</div><div>+-- Append element (array | element)</div><div>+CREATE OPERATOR | (</div><div>+    LEFTARG = anyarray,</div><div>+    RIGHTARG = anyelement,</div><div>+    PROCEDURE = anyarray_union_elem</div><div>+);</div><div>+</div><div>+-- Set difference (array - array)</div><div>+CREATE OPERATOR - (</div><div>+    LEFTARG = anyarray,</div><div>+    RIGHTARG = anyarray,</div><div>+    PROCEDURE = anyarray_difference</div><div>+);</div><div>+</div><div>+-- Remove all occurrences of element (array - element)</div><div>+CREATE OPERATOR - (</div><div>+    LEFTARG = anyarray,</div><div>+    RIGHTARG = anyelement,</div><div>+    PROCEDURE = anyarray_difference_elem</div><div>+);</div><div>+</div><div>+--</div><div>+-- Boolean query type</div><div>+--</div><div>+</div><div>+CREATE FUNCTION anyquery_in(cstring)</div><div>+RETURNS anyquery</div><div>+AS 'MODULE_PATHNAME', 'anyquery_in'</div><div>+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;</div><div>+</div><div>+CREATE FUNCTION anyquery_out(anyquery)</div><div>+RETURNS cstring</div><div>+AS 'MODULE_PATHNAME', 'anyquery_out'</div><div>+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;</div><div>+</div><div>+CREATE TYPE anyquery (</div><div>+    INTERNALLENGTH = -1,</div><div>+    INPUT = anyquery_in,</div><div>+    OUTPUT = anyquery_out,</div><div>+    STORAGE = extended</div><div>+);</div><div>+</div><div>+CREATE FUNCTION anyquery_querytree(anyquery)</div><div>+RETURNS text</div><div>+AS 'MODULE_PATHNAME', 'anyquery_querytree'</div><div>+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;</div><div>+</div><div>+CREATE FUNCTION anyarray_boolop(anyarray, anyquery)</div><div>+RETURNS bool</div><div>+AS 'MODULE_PATHNAME', 'anyarray_boolop'</div><div>+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;</div><div>+</div><div>+CREATE FUNCTION anyquery_boolop_rev(anyquery, anyarray)</div><div>+RETURNS bool</div><div>+AS 'MODULE_PATHNAME', 'anyquery_boolop_rev'</div><div>+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;</div><div>+</div><div>+CREATE OPERATOR @@ (</div><div>+    LEFTARG = anyarray,</div><div>+    RIGHTARG = anyquery,</div><div>+    PROCEDURE = anyarray_boolop,</div><div>+    COMMUTATOR = '~~',</div><div>+    RESTRICT = contsel,</div><div>+    JOIN = contjoinsel</div><div>+);</div><div>+</div><div>+CREATE OPERATOR ~~ (</div><div>+    LEFTARG = anyquery,</div><div>+    RIGHTARG = anyarray,</div><div>+    PROCEDURE = anyquery_boolop_rev,</div><div>+    COMMUTATOR = '@@',</div><div>+    RESTRICT = contsel,</div><div>+    JOIN = contjoinsel</div><div>+);</div><div>+</div><div>+--</div><div>+-- GiST opclass (signature-based)</div><div>+--</div><div>+</div><div>+CREATE FUNCTION anyarray_gist_key_in(cstring)</div><div>+RETURNS anyarray_gist_key</div><div>+AS 'MODULE_PATHNAME', 'anyarray_gist_key_in'</div><div>+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;</div><div>+</div><div>+CREATE FUNCTION anyarray_gist_key_out(anyarray_gist_key)</div><div>+RETURNS cstring</div><div>+AS 'MODULE_PATHNAME', 'anyarray_gist_key_out'</div><div>+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;</div><div>+</div><div>+CREATE TYPE anyarray_gist_key (</div><div>+    INTERNALLENGTH = -1,</div><div>+    INPUT = anyarray_gist_key_in,</div><div>+    OUTPUT = anyarray_gist_key_out</div><div>+);</div><div>+</div><div>+CREATE FUNCTION anyarray_gist_consistent(internal, anyarray, smallint, oid, internal)</div><div>+RETURNS bool</div><div>+AS 'MODULE_PATHNAME', 'anyarray_gist_consistent'</div><div>+LANGUAGE C IMMUTABLE PARALLEL SAFE;</div><div>+</div><div>+CREATE FUNCTION anyarray_gist_compress(internal)</div><div>+RETURNS internal</div><div>+AS 'MODULE_PATHNAME', 'anyarray_gist_compress'</div><div>+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;</div><div>+</div><div>+CREATE FUNCTION anyarray_gist_decompress(internal)</div><div>+RETURNS internal</div><div>+AS 'MODULE_PATHNAME', 'anyarray_gist_decompress'</div><div>+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;</div><div>+</div><div>+CREATE FUNCTION anyarray_gist_union(internal, internal)</div><div>+RETURNS anyarray_gist_key</div><div>+AS 'MODULE_PATHNAME', 'anyarray_gist_union'</div><div>+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;</div><div>+</div><div>+CREATE FUNCTION anyarray_gist_same(anyarray_gist_key, anyarray_gist_key, internal)</div><div>+RETURNS internal</div><div>+AS 'MODULE_PATHNAME', 'anyarray_gist_same'</div><div>+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;</div><div>+</div><div>+CREATE FUNCTION anyarray_gist_penalty(internal, internal, internal)</div><div>+RETURNS internal</div><div>+AS 'MODULE_PATHNAME', 'anyarray_gist_penalty'</div><div>+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;</div><div>+</div><div>+CREATE FUNCTION anyarray_gist_picksplit(internal, internal)</div><div>+RETURNS internal</div><div>+AS 'MODULE_PATHNAME', 'anyarray_gist_picksplit'</div><div>+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;</div><div>+</div><div>+CREATE FUNCTION anyarray_gist_options(internal)</div><div>+RETURNS void</div><div>+AS 'MODULE_PATHNAME', 'anyarray_gist_options'</div><div>+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;</div><div>+</div><div>+CREATE OPERATOR CLASS anyarray_gist_ops</div><div>+FOR TYPE anyarray USING gist</div><div>+AS</div><div>+    OPERATOR    3    &amp;&amp;,</div><div>+    OPERATOR    7    @&gt;,</div><div>+    OPERATOR    8    &lt;@,</div><div>+    OPERATOR    18    =,</div><div>+    OPERATOR    20    @@ (anyarray, anyquery),</div><div>+    FUNCTION    1    anyarray_gist_consistent(internal, anyarray, smallint, oid, internal),</div><div>+    FUNCTION    2    anyarray_gist_union(internal, internal),</div><div>+    FUNCTION    3    anyarray_gist_compress(internal),</div><div>+    FUNCTION    4    anyarray_gist_decompress(internal),</div><div>+    FUNCTION    5    anyarray_gist_penalty(internal, internal, internal),</div><div>+    FUNCTION    6    anyarray_gist_picksplit(internal, internal),</div><div>+    FUNCTION    7    anyarray_gist_same(anyarray_gist_key, anyarray_gist_key, internal),</div><div>+    FUNCTION    10    anyarray_gist_options(internal),</div><div>+    STORAGE        anyarray_gist_key;</div><div>+</div><div>+--</div><div>+-- GIN opclasses (per concrete element type, supporting standard ops + @@)</div><div>+--</div><div>+</div><div>+CREATE FUNCTION anyarray_gin_extract_query_int8(</div><div>+    int8[], internal, smallint, internal, internal, internal, internal)</div><div>+RETURNS internal</div><div>+AS 'MODULE_PATHNAME', 'anyarray_gin_extract_query_int8'</div><div>+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;</div><div>+</div><div>+CREATE FUNCTION anyarray_gin_consistent_int8(</div><div>+    internal, smallint, int8[], integer, internal, internal, internal, internal)</div><div>+RETURNS bool</div><div>+AS 'MODULE_PATHNAME', 'anyarray_gin_consistent_int8'</div><div>+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;</div><div>+</div><div>+CREATE OPERATOR CLASS int8_anyquery_gin_ops</div><div>+FOR TYPE int8[] USING gin</div><div>+AS</div><div>+    OPERATOR    1    &amp;&amp; (anyarray, anyarray),</div><div>+    OPERATOR    2    @&gt; (anyarray, anyarray),</div><div>+    OPERATOR    3    &lt;@ (anyarray, anyarray),</div><div>+    OPERATOR    4    = (anyarray, anyarray),</div><div>+    OPERATOR    5    @@ (anyarray, anyquery),</div><div>+    FUNCTION    1    btint8cmp(int8, int8),</div><div>+    FUNCTION    2    ginarrayextract(anyarray, internal, internal),</div><div>+    FUNCTION    3    anyarray_gin_extract_query_int8(int8[], internal, smallint, internal, internal, internal, internal),</div><div>+    FUNCTION    4    anyarray_gin_consistent_int8(internal, smallint, int8[], integer, internal, internal, internal, internal),</div><div>+    STORAGE        int8;</div><div>+</div><div>+CREATE FUNCTION anyarray_gin_extract_query_uuid(</div><div>+    uuid[], internal, smallint, internal, internal, internal, internal)</div><div>+RETURNS internal</div><div>+AS 'MODULE_PATHNAME', 'anyarray_gin_extract_query_uuid'</div><div>+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;</div><div>+</div><div>+CREATE FUNCTION anyarray_gin_consistent_uuid(</div><div>+    internal, smallint, uuid[], integer, internal, internal, internal, internal)</div><div>+RETURNS bool</div><div>+AS 'MODULE_PATHNAME', 'anyarray_gin_consistent_uuid'</div><div>+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;</div><div>+</div><div>+CREATE OPERATOR CLASS uuid_anyquery_gin_ops</div><div>+FOR TYPE uuid[] USING gin</div><div>+AS</div><div>+    OPERATOR    1    &amp;&amp; (anyarray, anyarray),</div><div>+    OPERATOR    2    @&gt; (anyarray, anyarray),</div><div>+    OPERATOR    3    &lt;@ (anyarray, anyarray),</div><div>+    OPERATOR    4    = (anyarray, anyarray),</div><div>+    OPERATOR    5    @@ (anyarray, anyquery),</div><div>+    FUNCTION    1    uuid_cmp(uuid, uuid),</div><div>+    FUNCTION    2    ginarrayextract(anyarray, internal, internal),</div><div>+    FUNCTION    3    anyarray_gin_extract_query_uuid(uuid[], internal, smallint, internal, internal, internal, internal),</div><div>+    FUNCTION    4    anyarray_gin_consistent_uuid(internal, smallint, uuid[], integer, internal, internal, internal, internal),</div><div>+    STORAGE        uuid;</div><div>+</div><div>+CREATE FUNCTION anyarray_gin_extract_query_text(</div><div>+    text[], internal, smallint, internal, internal, internal, internal)</div><div>+RETURNS internal</div><div>+AS 'MODULE_PATHNAME', 'anyarray_gin_extract_query_text'</div><div>+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;</div><div>+</div><div>+CREATE FUNCTION anyarray_gin_consistent_text(</div><div>+    internal, smallint, text[], integer, internal, internal, internal, internal)</div><div>+RETURNS bool</div><div>+AS 'MODULE_PATHNAME', 'anyarray_gin_consistent_text'</div><div>+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;</div><div>+</div><div>+CREATE OPERATOR CLASS text_anyquery_gin_ops</div><div>+FOR TYPE text[] USING gin</div><div>+AS</div><div>+    OPERATOR    1    &amp;&amp; (anyarray, anyarray),</div><div>+    OPERATOR    2    @&gt; (anyarray, anyarray),</div><div>+    OPERATOR    3    &lt;@ (anyarray, anyarray),</div><div>+    OPERATOR    4    = (anyarray, anyarray),</div><div>+    OPERATOR    5    @@ (anyarray, anyquery),</div><div>+    FUNCTION    1    bttextcmp(text, text),</div><div>+    FUNCTION    2    ginarrayextract(anyarray, internal, internal),</div><div>+    FUNCTION    3    anyarray_gin_extract_query_text(text[], internal, smallint, internal, internal, internal, internal),</div><div>+    FUNCTION    4    anyarray_gin_consistent_text(internal, smallint, text[], integer, internal, internal, internal, internal),</div><div>+    STORAGE        text;</div><div>diff --git a/contrib/anyarray/anyarray.c b/contrib/anyarray/anyarray.c</div><div>new file mode 100644</div><div>index 00000000000..0a2ab2153c8</div><div>--- /dev/null</div><div>+++ b/contrib/anyarray/anyarray.c</div><div>@@ -0,0 +1,116 @@</div><div>+/*-------------------------------------------------------------------------</div><div>+ *</div><div>+ * anyarray.c</div><div>+ *        Common code for the anyarray extension.</div><div>+ *</div><div>+ * This extension extends PostgreSQL with intarray-style operations and</div><div>+ * index support that work for arrays of any element type with a default</div><div>+ * btree opclass.  It is a generalization of the contrib/intarray module.</div><div>+ *</div><div>+ * Copyright (c) 2026, PostgreSQL Global Development Group</div><div>+ *</div><div>+ * IDENTIFICATION</div><div>+ *        contrib/anyarray/anyarray.c</div><div>+ *</div><div>+ *-------------------------------------------------------------------------</div><div>+ */</div><div>+</div><div>+#include "postgres.h"</div><div>+</div><div>+#include "anyarray.h"</div><div>+#include "catalog/pg_type.h"</div><div>+#include "utils/builtins.h"</div><div>+#include "utils/lsyscache.h"</div><div>+</div><div>+PG_MODULE_MAGIC_EXT(</div><div>+                    .name = "anyarray",</div><div>+                    .version = PG_VERSION</div><div>+);</div><div>+</div><div>+/*</div><div>+ * anyarray_get_meta</div><div>+ *        Fetch (and cache) type metadata for the given element type.</div><div>+ *</div><div>+ * The cache lives in fcinfo-&gt;flinfo-&gt;fn_extra so we pay the catalog lookup</div><div>+ * cost only once per call site.  If "need_hash" is true the element type</div><div>+ * must additionally provide a default hash function; otherwise only a btree</div><div>+ * comparison function is required.</div><div>+ */</div><div>+AnyArrayTypeInfo *</div><div>+anyarray_get_meta(FunctionCallInfo fcinfo, Oid element_type, bool need_hash)</div><div>+{<!-- --></div><div>+    AnyArrayTypeInfo *meta = (AnyArrayTypeInfo *) fcinfo-&gt;flinfo-&gt;fn_extra;</div><div>+    TypeCacheEntry *typentry;</div><div>+    uint32        flags;</div><div>+</div><div>+    if (meta == NULL)</div><div>+    {<!-- --></div><div>+        meta = (AnyArrayTypeInfo *)</div><div>+            MemoryContextAllocZero(fcinfo-&gt;flinfo-&gt;fn_mcxt,</div><div>+                                   sizeof(AnyArrayTypeInfo));</div><div>+        fcinfo-&gt;flinfo-&gt;fn_extra = meta;</div><div>+        meta-&gt;element_type = InvalidOid;</div><div>+    }</div><div>+</div><div>+    if (meta-&gt;element_type == element_type &amp;&amp; (!need_hash || meta-&gt;have_hash))</div><div>+        return meta;</div><div>+</div><div>+    flags = TYPECACHE_CMP_PROC_FINFO | TYPECACHE_EQ_OPR_FINFO;</div><div>+    if (need_hash)</div><div>+        flags |= TYPECACHE_HASH_PROC_FINFO;</div><div>+</div><div>+    typentry = lookup_type_cache(element_type, flags);</div><div>+</div><div>+    if (!OidIsValid(typentry-&gt;cmp_proc_finfo.fn_oid))</div><div>+        ereport(ERROR,</div><div>+                (errcode(ERRCODE_UNDEFINED_FUNCTION),</div><div>+                 errmsg("could not identify a comparison function for type %s",</div><div>+                        format_type_be(element_type))));</div><div>+</div><div>+    if (!OidIsValid(typentry-&gt;eq_opr_finfo.fn_oid))</div><div>+        ereport(ERROR,</div><div>+                (errcode(ERRCODE_UNDEFINED_FUNCTION),</div><div>+                 errmsg("could not identify an equality operator for type %s",</div><div>+                        format_type_be(element_type))));</div><div>+</div><div>+    if (need_hash &amp;&amp; !OidIsValid(typentry-&gt;hash_proc_finfo.fn_oid))</div><div>+        ereport(ERROR,</div><div>+                (errcode(ERRCODE_UNDEFINED_FUNCTION),</div><div>+                 errmsg("could not identify a hash function for type %s",</div><div>+                        format_type_be(element_type))));</div><div>+</div><div>+    meta-&gt;element_type = element_type;</div><div>+    get_typlenbyvalalign(element_type, &amp;meta-&gt;typlen, &amp;meta-&gt;typbyval,</div><div>+                         &amp;meta-&gt;typalign);</div><div>+    meta-&gt;typcollation = typentry-&gt;typcollation;</div><div>+    fmgr_info_cxt(typentry-&gt;cmp_proc_finfo.fn_oid, &amp;meta-&gt;cmp_proc,</div><div>+                  fcinfo-&gt;flinfo-&gt;fn_mcxt);</div><div>+    fmgr_info_cxt(typentry-&gt;eq_opr_finfo.fn_oid, &amp;meta-&gt;eq_proc,</div><div>+                  fcinfo-&gt;flinfo-&gt;fn_mcxt);</div><div>+    if (need_hash)</div><div>+    {<!-- --></div><div>+        fmgr_info_cxt(typentry-&gt;hash_proc_finfo.fn_oid, &amp;meta-&gt;hash_proc,</div><div>+                      fcinfo-&gt;flinfo-&gt;fn_mcxt);</div><div>+        meta-&gt;have_hash = true;</div><div>+    }</div><div>+    else</div><div>+        meta-&gt;have_hash = false;</div><div>+</div><div>+    return meta;</div><div>+}</div><div>+</div><div>+/*</div><div>+ * anyarray_cmp_datum</div><div>+ *        qsort_arg-compatible comparator delegating to the type's btree cmp.</div><div>+ */</div><div>+int</div><div>+anyarray_cmp_datum(const void *a, const void *b, void *arg)</div><div>+{<!-- --></div><div>+    AnyArrayTypeInfo *meta = (AnyArrayTypeInfo *) arg;</div><div>+    Datum        d1 = *((const Datum *) a);</div><div>+    Datum        d2 = *((const Datum *) b);</div><div>+    Datum        result;</div><div>+</div><div>+    result = FunctionCall2Coll(&amp;meta-&gt;cmp_proc, meta-&gt;typcollation, d1, d2);</div><div>+    return DatumGetInt32(result);</div><div>+}</div><div>diff --git a/contrib/anyarray/anyarray.control b/contrib/anyarray/anyarray.control</div><div>new file mode 100644</div><div>index 00000000000..2478f2d93d7</div><div>--- /dev/null</div><div>+++ b/contrib/anyarray/anyarray.control</div><div>@@ -0,0 +1,6 @@</div><div>+# anyarray extension</div><div>+comment = 'Operations and indexes for arrays of any type'</div><div>+default_version = '1.0'</div><div>+module_pathname = '$libdir/anyarray'</div><div>+relocatable = true</div><div>+trusted = false</div><div>diff --git a/contrib/anyarray/anyarray.h b/contrib/anyarray/anyarray.h</div><div>new file mode 100644</div><div>index 00000000000..f59ac9de749</div><div>--- /dev/null</div><div>+++ b/contrib/anyarray/anyarray.h</div><div>@@ -0,0 +1,184 @@</div><div>+/*-------------------------------------------------------------------------</div><div>+ *</div><div>+ * anyarray.h</div><div>+ *        Shared declarations for the anyarray extension.</div><div>+ *</div><div>+ * Copyright (c) 2026, PostgreSQL Global Development Group</div><div>+ *</div><div>+ * IDENTIFICATION</div><div>+ *        contrib/anyarray/anyarray.h</div><div>+ *</div><div>+ *-------------------------------------------------------------------------</div><div>+ */</div><div>+#ifndef ANYARRAY_H</div><div>+#define ANYARRAY_H</div><div>+</div><div>+#include "access/gist.h"</div><div>+#include "fmgr.h"</div><div>+#include "utils/array.h"</div><div>+#include "utils/typcache.h"</div><div>+</div><div>+/*</div><div>+ * Per-call cached element type metadata.</div><div>+ *</div><div>+ * Stored in fcinfo-&gt;flinfo-&gt;fn_extra so we look up the type once per</div><div>+ * planner-level call site.  All entries are populated by anyarray_get_meta().</div><div>+ */</div><div>+typedef struct AnyArrayTypeInfo</div><div>+{<!-- --></div><div>+    Oid            element_type;    /* element OID, or InvalidOid if not</div><div>+                                 * initialized */</div><div>+    int16        typlen;</div><div>+    bool        typbyval;</div><div>+    char        typalign;</div><div>+    Oid            typcollation;    /* default collation for comparisons */</div><div>+    FmgrInfo    cmp_proc;        /* btree comparison function for element_type */</div><div>+    FmgrInfo    eq_proc;        /* equality function for element_type */</div><div>+    FmgrInfo    hash_proc;        /* hash function for element_type (optional) */</div><div>+    bool        have_hash;        /* whether hash_proc was filled in */</div><div>+} AnyArrayTypeInfo;</div><div>+</div><div>+/* Reject the kinds of input we do not handle. */</div><div>+#define ANYARRAY_CHECK_ARRAY(arr) \</div><div>+    do { \</div><div>+        if (ARR_NDIM(arr) &gt; 1) \</div><div>+            ereport(ERROR, \</div><div>+                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), \</div><div>+                     errmsg("multidimensional arrays are not supported"))); \</div><div>+        if (ARR_HASNULL(arr) &amp;&amp; array_contains_nulls(arr)) \</div><div>+            ereport(ERROR, \</div><div>+                    (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), \</div><div>+                     errmsg("array must not contain nulls"))); \</div><div>+    } while (0)</div><div>+</div><div>+#define ANYARRAY_NELEMS(arr) \</div><div>+    (ARR_NDIM(arr) &gt; 0 ? ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr)) : 0)</div><div>+</div><div>+/*</div><div>+ * Initialize / refresh AnyArrayTypeInfo for a given element type.</div><div>+ *</div><div>+ * Allocates the struct in fcinfo-&gt;flinfo-&gt;fn_mcxt on first use; on subsequent</div><div>+ * calls reuses the cache unless the element type changed.  Reports an error</div><div>+ * via ereport() if the element type lacks a btree comparison operator</div><div>+ * (need_hash == true additionally requires a hash function).</div><div>+ */</div><div>+extern AnyArrayTypeInfo *anyarray_get_meta(FunctionCallInfo fcinfo,</div><div>+                                           Oid element_type,</div><div>+                                           bool need_hash);</div><div>+</div><div>+/*</div><div>+ * Comparison helper used both as a qsort_arg callback and directly.</div><div>+ * "arg" must be a valid AnyArrayTypeInfo *.</div><div>+ */</div><div>+extern int    anyarray_cmp_datum(const void *a, const void *b, void *arg);</div><div>+</div><div>+/*****************************************************************************</div><div>+ *  Boolean query type</div><div>+ *</div><div>+ *  An anyquery value is a boolean expression in postfix notation whose leaves</div><div>+ *  are textual representations of values.  The element type is not known at</div><div>+ *  parse time; it is supplied at @@-time by the array operand, and the value</div><div>+ *  strings are parsed lazily through the element type's text input function.</div><div>+ *</div><div>+ *  On-disk layout:</div><div>+ *</div><div>+ *     +-----------------------------+</div><div>+ *     | varlena header              |</div><div>+ *     | int32  size      (n items)  |</div><div>+ *     | int32  str_off              |  -- byte offset to string heap</div><div>+ *     | int32  str_len              |</div><div>+ *     | AnyQueryItem items[size]    |</div><div>+ *     | &lt;padding&gt;                   |</div><div>+ *     | char   strings[str_len]     |  -- null-terminated value strings</div><div>+ *     +-----------------------------+</div><div>+ *****************************************************************************/</div><div>+</div><div>+/* item.type values */</div><div>+#define ANYQ_VAL    1</div><div>+#define ANYQ_OPR    2</div><div>+</div><div>+/* operator codes (also used in the input grammar) */</div><div>+#define ANYQ_AND    '&amp;'</div><div>+#define ANYQ_OR        '|'</div><div>+#define ANYQ_NOT    '!'</div><div>+</div><div>+typedef struct AnyQueryItem</div><div>+{<!-- --></div><div>+    int16        type;            /* ANYQ_VAL or ANYQ_OPR */</div><div>+    int16        left;            /* offset to left-operand item (OPR only) */</div><div>+    int32        payload;        /* VAL: offset into string heap; OPR: one of</div><div>+                                 * ANYQ_AND/OR/NOT */</div><div>+} AnyQueryItem;</div><div>+</div><div>+typedef struct AnyQuery</div><div>+{<!-- --></div><div>+    int32        vl_len_;        /* varlena header (do not touch directly!) */</div><div>+    int32        size;            /* number of items */</div><div>+    int32        str_off;        /* byte offset to string heap */</div><div>+    int32        str_len;        /* length of string heap */</div><div>+    AnyQueryItem items[FLEXIBLE_ARRAY_MEMBER];</div><div>+    /* followed by null-terminated value strings */</div><div>+} AnyQuery;</div><div>+</div><div>+#define ANYQUERY_HDRSIZE            offsetof(AnyQuery, items)</div><div>+#define ANYQUERY_ITEMS(q)            ((q)-&gt;items)</div><div>+#define ANYQUERY_STRING(q, item)    ((const char *) (q) + (q)-&gt;str_off + (item)-&gt;payload)</div><div>+#define ANYQUERY_MAXITEMS \</div><div>+    ((MaxAllocSize - ANYQUERY_HDRSIZE) / sizeof(AnyQueryItem))</div><div>+</div><div>+#define DatumGetAnyQueryP(X)        ((AnyQuery *) PG_DETOAST_DATUM(X))</div><div>+#define PG_GETARG_ANYQUERY_P(n)        DatumGetAnyQueryP(PG_GETARG_DATUM(n))</div><div>+</div><div>+/*****************************************************************************</div><div>+ *  GiST signature key</div><div>+ *</div><div>+ *  Each indexed array is summarized as a fixed-size bit vector ("signature").</div><div>+ *  Each element contributes a single bit, chosen as</div><div>+ *      hash(element) mod (siglen * 8).</div><div>+ *  Internal node keys are bitwise unions of their children; the ALLISTRUE</div><div>+ *  flag short-circuits storage when every bit would be set.</div><div>+ *****************************************************************************/</div><div>+</div><div>+#define ANYARRAY_SIGLEN_DEFAULT        (63 * 4)    /* 252 bytes -&gt; 2016 bits */</div><div>+#define ANYARRAY_SIGLEN_MAX            GISTMaxIndexKeySize</div><div>+#define ANYARRAY_ALLISTRUE            0x01</div><div>+</div><div>+typedef struct AnyArrayGistKey</div><div>+{<!-- --></div><div>+    int32        vl_len_;        /* varlena header (do not touch directly!) */</div><div>+    int32        flag;</div><div>+    char        data[FLEXIBLE_ARRAY_MEMBER];    /* bit vector, siglen bytes */</div><div>+} AnyArrayGistKey;</div><div>+</div><div>+typedef struct AnyArrayGistOptions</div><div>+{<!-- --></div><div>+    int32        vl_len_;</div><div>+    int            siglen;            /* signature length in bytes */</div><div>+} AnyArrayGistOptions;</div><div>+</div><div>+#define ANYARRAY_GET_SIGLEN()        (PG_HAS_OPCLASS_OPTIONS() ? \</div><div>+                                     ((AnyArrayGistOptions *) PG_GET_OPCLASS_OPTIONS())-&gt;siglen : \</div><div>+                                     ANYARRAY_SIGLEN_DEFAULT)</div><div>+</div><div>+#define ANYARRAY_GKEY_HDR            (VARHDRSZ + sizeof(int32))</div><div>+#define ANYARRAY_GKEY_SIZE(flag, siglen) \</div><div>+    (ANYARRAY_GKEY_HDR + (((flag) &amp; ANYARRAY_ALLISTRUE) ? 0 : (siglen)))</div><div>+#define ANYARRAY_GKEY_ISALLTRUE(k)    (((AnyArrayGistKey *) (k))-&gt;flag &amp; ANYARRAY_ALLISTRUE)</div><div>+#define ANYARRAY_GKEY_SIGN(k)        ((unsigned char *) (((AnyArrayGistKey *) (k))-&gt;data))</div><div>+</div><div>+/* GIN strategy numbers; the first four match core's gin/array_ops */</div><div>+#define ANYARRAY_GIN_OVERLAP_STRATEGY    1</div><div>+#define ANYARRAY_GIN_CONTAINS_STRATEGY    2</div><div>+#define ANYARRAY_GIN_CONTAINED_STRATEGY    3</div><div>+#define ANYARRAY_GIN_EQUAL_STRATEGY        4</div><div>+#define ANYARRAY_GIN_BOOLEAN_STRATEGY    5</div><div>+</div><div>+#define ANYARRAY_HASHVAL(h, siglen)    ((unsigned int) (h) % ((siglen) * BITS_PER_BYTE))</div><div>+#define ANYARRAY_SETBIT(sig, h, siglen) \</div><div>+    ((sig)[(ANYARRAY_HASHVAL((h), (siglen)) / BITS_PER_BYTE)] |= \</div><div>+        (1 &lt;&lt; (ANYARRAY_HASHVAL((h), (siglen)) % BITS_PER_BYTE)))</div><div>+#define ANYARRAY_GETBIT(sig, h, siglen) \</div><div>+    (((sig)[(ANYARRAY_HASHVAL((h), (siglen)) / BITS_PER_BYTE)] &gt;&gt; \</div><div>+        (ANYARRAY_HASHVAL((h), (siglen)) % BITS_PER_BYTE)) &amp; 1)</div><div>+</div><div>+#endif                            /* ANYARRAY_H */</div><div>diff --git a/contrib/anyarray/anyarray_bool.c b/contrib/anyarray/anyarray_bool.c</div><div>new file mode 100644</div><div>index 00000000000..325619837ef</div><div>--- /dev/null</div><div>+++ b/contrib/anyarray/anyarray_bool.c</div><div>@@ -0,0 +1,664 @@</div><div>+/*-------------------------------------------------------------------------</div><div>+ *</div><div>+ * anyarray_bool.c</div><div>+ *        Boolean query type for anyarray.</div><div>+ *</div><div>+ * Provides the anyquery type and the @@ operator.  A query value is a</div><div>+ * boolean expression whose leaves are text tokens; the element type is</div><div>+ * supplied at @@-time by the array operand, and the leaves are parsed</div><div>+ * through the element type's text input function.</div><div>+ *</div><div>+ * Grammar:</div><div>+ *</div><div>+ *      expr        ::= or_expr</div><div>+ *      or_expr     ::= and_expr ( '|' and_expr )*</div><div>+ *      and_expr    ::= unary_expr ( '&amp;' unary_expr )*</div><div>+ *      unary_expr  ::= '!' unary_expr | atom</div><div>+ *      atom        ::= VALUE | '(' expr ')'</div><div>+ *      VALUE       ::= bare_token | quoted_string</div><div>+ *      bare_token  ::= any run of characters that are not whitespace,</div><div>+ *                      '&amp;', '|', '!', '(', ')', or '"'</div><div>+ *      quoted_string := '"' chars-with-backslash-escapes '"'</div><div>+ *</div><div>+ *</div><div>+ * Copyright (c) 2026, PostgreSQL Global Development Group</div><div>+ *</div><div>+ * IDENTIFICATION</div><div>+ *        contrib/anyarray/anyarray_bool.c</div><div>+ *</div><div>+ *-------------------------------------------------------------------------</div><div>+ */</div><div>+</div><div>+#include "postgres.h"</div><div>+</div><div>+#include "anyarray.h"</div><div>+</div><div>+#include "lib/stringinfo.h"</div><div>+#include "miscadmin.h"</div><div>+#include "nodes/miscnodes.h"</div><div>+#include "utils/array.h"</div><div>+#include "utils/builtins.h"</div><div>+#include "utils/lsyscache.h"</div><div>+#include "utils/memutils.h"</div><div>+</div><div>+PG_FUNCTION_INFO_V1(anyquery_in);</div><div>+PG_FUNCTION_INFO_V1(anyquery_out);</div><div>+PG_FUNCTION_INFO_V1(anyarray_boolop);</div><div>+PG_FUNCTION_INFO_V1(anyquery_boolop_rev);</div><div>+PG_FUNCTION_INFO_V1(anyquery_querytree);</div><div>+</div><div>+</div><div>+/* ------------------------------------------------------------------------</div><div>+ *  Parser</div><div>+ * ------------------------------------------------------------------------</div><div>+ */</div><div>+</div><div>+/*</div><div>+ * Working state used while building the postfix item list.</div><div>+ *</div><div>+ * Items are emitted in postfix (reverse polish) order directly into the</div><div>+ * "items" array.  Value strings are concatenated into "strs"; each VAL item</div><div>+ * stores the byte offset of its string within strs-&gt;data.</div><div>+ */</div><div>+typedef struct ParserState</div><div>+{<!-- --></div><div>+    const char *cur;</div><div>+    const char *end;</div><div>+    AnyQueryItem *items;</div><div>+    int            nitems;</div><div>+    int            capitems;</div><div>+    StringInfoData strs;</div><div>+    struct Node *escontext;</div><div>+} ParserState;</div><div>+</div><div>+#define PARSE_FAIL(state, errc, ...) \</div><div>+    do { \</div><div>+        errsave((state)-&gt;escontext, \</div><div>+                (errcode(errc), \</div><div>+                 __VA_ARGS__)); \</div><div>+        return false; \</div><div>+    } while (0)</div><div>+</div><div>+static bool parse_expr(ParserState *state);</div><div>+</div><div>+static void</div><div>+skip_ws(ParserState *state)</div><div>+{<!-- --></div><div>+    while (state-&gt;cur &lt; state-&gt;end &amp;&amp;</div><div>+           (*state-&gt;cur == ' ' || *state-&gt;cur == '\t' ||</div><div>+            *state-&gt;cur == '\r' || *state-&gt;cur == '\n' ||</div><div>+            *state-&gt;cur == '\v' || *state-&gt;cur == '\f'))</div><div>+        state-&gt;cur++;</div><div>+}</div><div>+</div><div>+static bool</div><div>+is_value_char(char c)</div><div>+{<!-- --></div><div>+    if (c == '\0' || c == ' ' || c == '\t' || c == '\r' || c == '\n' ||</div><div>+        c == '\v' || c == '\f')</div><div>+        return false;</div><div>+    if (c == '&amp;' || c == '|' || c == '!' || c == '(' || c == ')' || c == '"')</div><div>+        return false;</div><div>+    return true;</div><div>+}</div><div>+</div><div>+static bool</div><div>+emit_item(ParserState *state, int16 type, int32 payload)</div><div>+{<!-- --></div><div>+    if (state-&gt;nitems == state-&gt;capitems)</div><div>+    {<!-- --></div><div>+        if ((size_t) state-&gt;capitems * 2 &gt; ANYQUERY_MAXITEMS)</div><div>+            PARSE_FAIL(state, ERRCODE_PROGRAM_LIMIT_EXCEEDED,</div><div>+                       errmsg("anyquery expression is too complex"));</div><div>+        state-&gt;capitems *= 2;</div><div>+        state-&gt;items = (AnyQueryItem *) repalloc(state-&gt;items,</div><div>+                                                 sizeof(AnyQueryItem) *</div><div>+                                                 state-&gt;capitems);</div><div>+    }</div><div>+    state-&gt;items[state-&gt;nitems].type = type;</div><div>+    state-&gt;items[state-&gt;nitems].left = 0;</div><div>+    state-&gt;items[state-&gt;nitems].payload = payload;</div><div>+    state-&gt;nitems++;</div><div>+    return true;</div><div>+}</div><div>+</div><div>+/*</div><div>+ * Consume a value token, append its string (with terminating NUL) to</div><div>+ * state-&gt;strs, and emit a VAL item whose payload is the byte offset of the</div><div>+ * string within strs-&gt;data.</div><div>+ */</div><div>+static bool</div><div>+parse_value(ParserState *state)</div><div>+{<!-- --></div><div>+    int32        off;</div><div>+</div><div>+    skip_ws(state);</div><div>+</div><div>+    if (state-&gt;cur &gt;= state-&gt;end)</div><div>+        PARSE_FAIL(state, ERRCODE_SYNTAX_ERROR,</div><div>+                   errmsg("unexpected end of input in anyquery"));</div><div>+</div><div>+    off = state-&gt;strs.len;</div><div>+</div><div>+    if (*state-&gt;cur == '"')</div><div>+    {<!-- --></div><div>+        state-&gt;cur++;            /* opening quote */</div><div>+        while (state-&gt;cur &lt; state-&gt;end &amp;&amp; *state-&gt;cur != '"')</div><div>+        {<!-- --></div><div>+            if (*state-&gt;cur == '\\' &amp;&amp; state-&gt;cur + 1 &lt; state-&gt;end)</div><div>+                state-&gt;cur++;</div><div>+            appendStringInfoChar(&amp;state-&gt;strs, *state-&gt;cur);</div><div>+            state-&gt;cur++;</div><div>+        }</div><div>+        if (state-&gt;cur &gt;= state-&gt;end)</div><div>+            PARSE_FAIL(state, ERRCODE_SYNTAX_ERROR,</div><div>+                       errmsg("unterminated quoted value in anyquery"));</div><div>+        state-&gt;cur++;            /* closing quote */</div><div>+    }</div><div>+    else if (is_value_char(*state-&gt;cur))</div><div>+    {<!-- --></div><div>+        while (state-&gt;cur &lt; state-&gt;end &amp;&amp; is_value_char(*state-&gt;cur))</div><div>+        {<!-- --></div><div>+            appendStringInfoChar(&amp;state-&gt;strs, *state-&gt;cur);</div><div>+            state-&gt;cur++;</div><div>+        }</div><div>+    }</div><div>+    else</div><div>+        PARSE_FAIL(state, ERRCODE_SYNTAX_ERROR,</div><div>+                   errmsg("expected value at character \"%c\"", *state-&gt;cur));</div><div>+</div><div>+    appendStringInfoChar(&amp;state-&gt;strs, '\0');</div><div>+    return emit_item(state, ANYQ_VAL, off);</div><div>+}</div><div>+</div><div>+static bool</div><div>+parse_atom(ParserState *state)</div><div>+{<!-- --></div><div>+    skip_ws(state);</div><div>+    if (state-&gt;cur &lt; state-&gt;end &amp;&amp; *state-&gt;cur == '(')</div><div>+    {<!-- --></div><div>+        state-&gt;cur++;</div><div>+        if (!parse_expr(state))</div><div>+            return false;</div><div>+        skip_ws(state);</div><div>+        if (state-&gt;cur &gt;= state-&gt;end || *state-&gt;cur != ')')</div><div>+            PARSE_FAIL(state, ERRCODE_SYNTAX_ERROR,</div><div>+                       errmsg("missing closing parenthesis in anyquery"));</div><div>+        state-&gt;cur++;</div><div>+        return true;</div><div>+    }</div><div>+    return parse_value(state);</div><div>+}</div><div>+</div><div>+static bool</div><div>+parse_not(ParserState *state)</div><div>+{<!-- --></div><div>+    skip_ws(state);</div><div>+    if (state-&gt;cur &lt; state-&gt;end &amp;&amp; *state-&gt;cur == '!')</div><div>+    {<!-- --></div><div>+        state-&gt;cur++;</div><div>+        if (!parse_not(state))</div><div>+            return false;</div><div>+        return emit_item(state, ANYQ_OPR, ANYQ_NOT);</div><div>+    }</div><div>+    return parse_atom(state);</div><div>+}</div><div>+</div><div>+static bool</div><div>+parse_and(ParserState *state)</div><div>+{<!-- --></div><div>+    if (!parse_not(state))</div><div>+        return false;</div><div>+    for (;;)</div><div>+    {<!-- --></div><div>+        skip_ws(state);</div><div>+        if (state-&gt;cur &gt;= state-&gt;end || *state-&gt;cur != '&amp;')</div><div>+            return true;</div><div>+        state-&gt;cur++;</div><div>+        if (!parse_not(state))</div><div>+            return false;</div><div>+        if (!emit_item(state, ANYQ_OPR, ANYQ_AND))</div><div>+            return false;</div><div>+    }</div><div>+}</div><div>+</div><div>+static bool</div><div>+parse_expr(ParserState *state)</div><div>+{<!-- --></div><div>+    check_stack_depth();</div><div>+</div><div>+    if (!parse_and(state))</div><div>+        return false;</div><div>+    for (;;)</div><div>+    {<!-- --></div><div>+        skip_ws(state);</div><div>+        if (state-&gt;cur &gt;= state-&gt;end || *state-&gt;cur != '|')</div><div>+            return true;</div><div>+        state-&gt;cur++;</div><div>+        if (!parse_and(state))</div><div>+            return false;</div><div>+        if (!emit_item(state, ANYQ_OPR, ANYQ_OR))</div><div>+            return false;</div><div>+    }</div><div>+}</div><div>+</div><div>+/*</div><div>+ * Compute the "left" field for every OPR item by walking the postfix array</div><div>+ * top-down.  Returns false on overflow of the int16 left field.</div><div>+ */</div><div>+static bool</div><div>+compute_lefts(ParserState *state, int *pos)</div><div>+{<!-- --></div><div>+    int            mypos;</div><div>+</div><div>+    check_stack_depth();</div><div>+</div><div>+    mypos = (*pos)--;</div><div>+    Assert(mypos &gt;= 0);</div><div>+</div><div>+    if (state-&gt;items[mypos].type == ANYQ_VAL)</div><div>+    {<!-- --></div><div>+        state-&gt;items[mypos].left = 0;</div><div>+        return true;</div><div>+    }</div><div>+    else if (state-&gt;items[mypos].payload == ANYQ_NOT)</div><div>+    {<!-- --></div><div>+        state-&gt;items[mypos].left = -1;</div><div>+        return compute_lefts(state, pos);</div><div>+    }</div><div>+    else</div><div>+    {<!-- --></div><div>+        int            delta;</div><div>+</div><div>+        /* binary operator: walk right operand */</div><div>+        if (!compute_lefts(state, pos))</div><div>+            return false;</div><div>+        delta = *pos - mypos;</div><div>+        if (delta &lt; PG_INT16_MIN)</div><div>+        {<!-- --></div><div>+            errsave(state-&gt;escontext,</div><div>+                    (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),</div><div>+                     errmsg("anyquery expression is too complex")));</div><div>+            return false;</div><div>+        }</div><div>+        state-&gt;items[mypos].left = (int16) delta;</div><div>+        return compute_lefts(state, pos);</div><div>+    }</div><div>+}</div><div>+</div><div>+</div><div>+/* ------------------------------------------------------------------------</div><div>+ *  Input / output / debug</div><div>+ * ------------------------------------------------------------------------</div><div>+ */</div><div>+</div><div>+Datum</div><div>+anyquery_in(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    char       *buf = PG_GETARG_CSTRING(0);</div><div>+    ParserState state;</div><div>+    AnyQuery   *out;</div><div>+    Size        items_bytes;</div><div>+    Size        total;</div><div>+    int            pos;</div><div>+</div><div>+    state.cur = buf;</div><div>+    state.end = buf + strlen(buf);</div><div>+    state.capitems = 16;</div><div>+    state.items = (AnyQueryItem *) palloc(sizeof(AnyQueryItem) *</div><div>+                                          state.capitems);</div><div>+    state.nitems = 0;</div><div>+    initStringInfo(&amp;state.strs);</div><div>+    state.escontext = fcinfo-&gt;context;</div><div>+</div><div>+    if (!parse_expr(&amp;state))</div><div>+        PG_RETURN_NULL();</div><div>+</div><div>+    skip_ws(&amp;state);</div><div>+    if (state.cur &lt; state.end)</div><div>+        ereturn(state.escontext, (Datum) 0,</div><div>+                (errcode(ERRCODE_SYNTAX_ERROR),</div><div>+                 errmsg("unexpected trailing input in anyquery")));</div><div>+</div><div>+    if (state.nitems == 0)</div><div>+        ereturn(state.escontext, (Datum) 0,</div><div>+                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),</div><div>+                 errmsg("empty anyquery")));</div><div>+</div><div>+    if ((size_t) state.nitems &gt; ANYQUERY_MAXITEMS)</div><div>+        ereturn(state.escontext, (Datum) 0,</div><div>+                (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),</div><div>+                 errmsg("anyquery has too many items (%d, maximum %zu)",</div><div>+                        state.nitems, ANYQUERY_MAXITEMS)));</div><div>+</div><div>+    pos = state.nitems - 1;</div><div>+    if (!compute_lefts(&amp;state, &amp;pos))</div><div>+        PG_RETURN_NULL();</div><div>+    Assert(pos == -1);</div><div>+</div><div>+    items_bytes = MAXALIGN(state.nitems * sizeof(AnyQueryItem));</div><div>+    total = ANYQUERY_HDRSIZE + items_bytes + state.strs.len;</div><div>+</div><div>+    out = (AnyQuery *) palloc0(total);</div><div>+    SET_VARSIZE(out, total);</div><div>+    out-&gt;size = state.nitems;</div><div>+    out-&gt;str_off = ANYQUERY_HDRSIZE + items_bytes;</div><div>+    out-&gt;str_len = state.strs.len;</div><div>+    memcpy(out-&gt;items, state.items, state.nitems * sizeof(AnyQueryItem));</div><div>+    memcpy((char *) out + out-&gt;str_off, state.strs.data, state.strs.len);</div><div>+</div><div>+    pfree(state.items);</div><div>+    pfree(state.strs.data);</div><div>+</div><div>+    PG_RETURN_POINTER(out);</div><div>+}</div><div>+</div><div>+/*</div><div>+ * Quote a value string if it contains anything the parser would consider</div><div>+ * special.  Otherwise emit it verbatim.</div><div>+ */</div><div>+static void</div><div>+append_value_token(StringInfo out, const char *s)</div><div>+{<!-- --></div><div>+    const char *p;</div><div>+    bool        need_quote = (*s == '\0');</div><div>+</div><div>+    for (p = s; *p; p++)</div><div>+    {<!-- --></div><div>+        if (!is_value_char(*p))</div><div>+        {<!-- --></div><div>+            need_quote = true;</div><div>+            break;</div><div>+        }</div><div>+    }</div><div>+</div><div>+    if (!need_quote)</div><div>+    {<!-- --></div><div>+        appendStringInfoString(out, s);</div><div>+        return;</div><div>+    }</div><div>+</div><div>+    appendStringInfoChar(out, '"');</div><div>+    for (p = s; *p; p++)</div><div>+    {<!-- --></div><div>+        if (*p == '"' || *p == '\\')</div><div>+            appendStringInfoChar(out, '\\');</div><div>+        appendStringInfoChar(out, *p);</div><div>+    }</div><div>+    appendStringInfoChar(out, '"');</div><div>+}</div><div>+</div><div>+/*</div><div>+ * Infix walker for the output function.  Returns the postfix index that</div><div>+ * "cur" decremented to so the caller can chain.</div><div>+ */</div><div>+static int</div><div>+infix_walk(StringInfo out, AnyQuery *q, int cur, bool top)</div><div>+{<!-- --></div><div>+    AnyQueryItem *it;</div><div>+</div><div>+    check_stack_depth();</div><div>+    Assert(cur &gt;= 0);</div><div>+    it = &amp;q-&gt;items[cur];</div><div>+</div><div>+    if (it-&gt;type == ANYQ_VAL)</div><div>+    {<!-- --></div><div>+        append_value_token(out, ANYQUERY_STRING(q, it));</div><div>+        return cur - 1;</div><div>+    }</div><div>+    else if (it-&gt;payload == ANYQ_NOT)</div><div>+    {<!-- --></div><div>+        AnyQueryItem *child = &amp;q-&gt;items[cur - 1];</div><div>+        bool        paren = (child-&gt;type == ANYQ_OPR);</div><div>+</div><div>+        appendStringInfoChar(out, '!');</div><div>+        if (paren)</div><div>+            appendStringInfoString(out, "( ");</div><div>+        cur = infix_walk(out, q, cur - 1, false);</div><div>+        if (paren)</div><div>+            appendStringInfoString(out, " )");</div><div>+        return cur;</div><div>+    }</div><div>+    else</div><div>+    {<!-- --></div><div>+        int            op = it-&gt;payload;</div><div>+        StringInfoData right;</div><div>+        int            next;</div><div>+</div><div>+        if (op == ANYQ_OR &amp;&amp; !top)</div><div>+            appendStringInfoString(out, "( ");</div><div>+</div><div>+        /* right operand first into a side buffer */</div><div>+        initStringInfo(&amp;right);</div><div>+        next = infix_walk(&amp;right, q, cur - 1, false);</div><div>+        /* left operand into the main buffer */</div><div>+        cur = infix_walk(out, q, next, false);</div><div>+</div><div>+        appendStringInfo(out, " %c %s", op, right.data);</div><div>+        pfree(right.data);</div><div>+</div><div>+        if (op == ANYQ_OR &amp;&amp; !top)</div><div>+            appendStringInfoString(out, " )");</div><div>+        return cur;</div><div>+    }</div><div>+}</div><div>+</div><div>+Datum</div><div>+anyquery_out(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    AnyQuery   *q = PG_GETARG_ANYQUERY_P(0);</div><div>+    StringInfoData out;</div><div>+</div><div>+    if (q-&gt;size &lt;= 0)</div><div>+        ereport(ERROR,</div><div>+                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),</div><div>+                 errmsg("empty anyquery")));</div><div>+</div><div>+    initStringInfo(&amp;out);</div><div>+    (void) infix_walk(&amp;out, q, q-&gt;size - 1, true);</div><div>+</div><div>+    PG_RETURN_CSTRING(out.data);</div><div>+}</div><div>+</div><div>+/*</div><div>+ * Debugging helper: produce a postfix string with operator codes spelled out.</div><div>+ * Mostly useful while writing tests.</div><div>+ */</div><div>+Datum</div><div>+anyquery_querytree(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    AnyQuery   *q = PG_GETARG_ANYQUERY_P(0);</div><div>+    StringInfoData out;</div><div>+    int            i;</div><div>+</div><div>+    initStringInfo(&amp;out);</div><div>+    for (i = 0; i &lt; q-&gt;size; i++)</div><div>+    {<!-- --></div><div>+        AnyQueryItem *it = &amp;q-&gt;items[i];</div><div>+</div><div>+        if (i &gt; 0)</div><div>+            appendStringInfoChar(&amp;out, ' ');</div><div>+        if (it-&gt;type == ANYQ_VAL)</div><div>+            append_value_token(&amp;out, ANYQUERY_STRING(q, it));</div><div>+        else</div><div>+            appendStringInfoChar(&amp;out, (char) it-&gt;payload);</div><div>+    }</div><div>+    PG_RETURN_TEXT_P(cstring_to_text_with_len(out.data, out.len));</div><div>+}</div><div>+</div><div>+</div><div>+/* ------------------------------------------------------------------------</div><div>+ *  Matching: anyarray @@ anyquery</div><div>+ * ------------------------------------------------------------------------</div><div>+ */</div><div>+</div><div>+typedef struct MatchContext</div><div>+{<!-- --></div><div>+    AnyArrayTypeInfo *meta;</div><div>+    Datum       *sorted;            /* sorted array elements (owned) */</div><div>+    int            nelems;</div><div>+    /* cached parsed values for each VAL item in the query */</div><div>+    Datum       *parsed;</div><div>+    bool       *parsed_valid;</div><div>+} MatchContext;</div><div>+</div><div>+/*</div><div>+ * Look up val in the sorted element array via binary search.</div><div>+ */</div><div>+static bool</div><div>+contains_value(MatchContext *ctx, Datum val)</div><div>+{<!-- --></div><div>+    int            lo = 0;</div><div>+    int            hi = ctx-&gt;nelems;</div><div>+</div><div>+    while (lo &lt; hi)</div><div>+    {<!-- --></div><div>+        int            mid = lo + (hi - lo) / 2;</div><div>+        int            c = DatumGetInt32(FunctionCall2Coll(&amp;ctx-&gt;meta-&gt;cmp_proc,</div><div>+                                                        ctx-&gt;meta-&gt;typcollation,</div><div>+                                                        ctx-&gt;sorted[mid],</div><div>+                                                        val));</div><div>+</div><div>+        if (c == 0)</div><div>+            return true;</div><div>+        if (c &lt; 0)</div><div>+            lo = mid + 1;</div><div>+        else</div><div>+            hi = mid;</div><div>+    }</div><div>+    return false;</div><div>+}</div><div>+</div><div>+/*</div><div>+ * Evaluate one node of the postfix tree.  Recursive on operators.</div><div>+ */</div><div>+static bool</div><div>+eval_item(AnyQuery *q, int idx, MatchContext *ctx, Oid input_func,</div><div>+          int input_typioparam, int32 input_typmod)</div><div>+{<!-- --></div><div>+    AnyQueryItem *it;</div><div>+</div><div>+    check_stack_depth();</div><div>+    Assert(idx &gt;= 0);</div><div>+    it = &amp;q-&gt;items[idx];</div><div>+</div><div>+    if (it-&gt;type == ANYQ_VAL)</div><div>+    {<!-- --></div><div>+        Datum        v;</div><div>+</div><div>+        if (!ctx-&gt;parsed_valid[idx])</div><div>+        {<!-- --></div><div>+            const char *s = ANYQUERY_STRING(q, it);</div><div>+</div><div>+            v = OidInputFunctionCall(input_func, (char *) s,</div><div>+                                     input_typioparam, input_typmod);</div><div>+            ctx-&gt;parsed[idx] = v;</div><div>+            ctx-&gt;parsed_valid[idx] = true;</div><div>+        }</div><div>+        return contains_value(ctx, ctx-&gt;parsed[idx]);</div><div>+    }</div><div>+    else if (it-&gt;payload == ANYQ_NOT)</div><div>+    {<!-- --></div><div>+        return !eval_item(q, idx - 1, ctx, input_func,</div><div>+                          input_typioparam, input_typmod);</div><div>+    }</div><div>+    else if (it-&gt;payload == ANYQ_AND)</div><div>+    {<!-- --></div><div>+        if (!eval_item(q, idx + it-&gt;left, ctx, input_func,</div><div>+                       input_typioparam, input_typmod))</div><div>+            return false;</div><div>+        return eval_item(q, idx - 1, ctx, input_func,</div><div>+                         input_typioparam, input_typmod);</div><div>+    }</div><div>+    else                        /* ANYQ_OR */</div><div>+    {<!-- --></div><div>+        if (eval_item(q, idx + it-&gt;left, ctx, input_func,</div><div>+                      input_typioparam, input_typmod))</div><div>+            return true;</div><div>+        return eval_item(q, idx - 1, ctx, input_func,</div><div>+                         input_typioparam, input_typmod);</div><div>+    }</div><div>+}</div><div>+</div><div>+static Datum</div><div>+do_boolop(FunctionCallInfo fcinfo, ArrayType *arr, AnyQuery *q)</div><div>+{<!-- --></div><div>+    AnyArrayTypeInfo *meta;</div><div>+    Datum       *values;</div><div>+    bool       *nulls;</div><div>+    int            nelems;</div><div>+    Oid            input_func;</div><div>+    Oid            input_typioparam;</div><div>+    bool        result;</div><div>+    MatchContext ctx;</div><div>+</div><div>+    ANYARRAY_CHECK_ARRAY(arr);</div><div>+</div><div>+    if (q-&gt;size &lt;= 0)</div><div>+        ereport(ERROR,</div><div>+                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),</div><div>+                 errmsg("empty anyquery")));</div><div>+</div><div>+    meta = anyarray_get_meta(fcinfo, ARR_ELEMTYPE(arr), false);</div><div>+</div><div>+    if (ARR_NDIM(arr) == 0)</div><div>+    {<!-- --></div><div>+        nelems = 0;</div><div>+        values = NULL;</div><div>+    }</div><div>+    else</div><div>+    {<!-- --></div><div>+        deconstruct_array(arr, meta-&gt;element_type, meta-&gt;typlen,</div><div>+                          meta-&gt;typbyval, meta-&gt;typalign,</div><div>+                          &amp;values, &amp;nulls, &amp;nelems);</div><div>+        pfree(nulls);</div><div>+        if (nelems &gt; 1)</div><div>+            qsort_arg(values, nelems, sizeof(Datum),</div><div>+                      anyarray_cmp_datum, meta);</div><div>+    }</div><div>+</div><div>+    getTypeInputInfo(meta-&gt;element_type, &amp;input_func, &amp;input_typioparam);</div><div>+</div><div>+    ctx.meta = meta;</div><div>+    ctx.sorted = values;</div><div>+    ctx.nelems = nelems;</div><div>+    ctx.parsed = (Datum *) palloc0(sizeof(Datum) * q-&gt;size);</div><div>+    ctx.parsed_valid = (bool *) palloc0(sizeof(bool) * q-&gt;size);</div><div>+</div><div>+    result = eval_item(q, q-&gt;size - 1, &amp;ctx, input_func,</div><div>+                       input_typioparam, -1);</div><div>+</div><div>+    pfree(ctx.parsed);</div><div>+    pfree(ctx.parsed_valid);</div><div>+    if (values)</div><div>+        pfree(values);</div><div>+</div><div>+    PG_RETURN_BOOL(result);</div><div>+}</div><div>+</div><div>+Datum</div><div>+anyarray_boolop(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    ArrayType  *arr = PG_GETARG_ARRAYTYPE_P(0);</div><div>+    AnyQuery   *q = PG_GETARG_ANYQUERY_P(1);</div><div>+    Datum        result = do_boolop(fcinfo, arr, q);</div><div>+</div><div>+    PG_FREE_IF_COPY(arr, 0);</div><div>+    PG_FREE_IF_COPY(q, 1);</div><div>+    return result;</div><div>+}</div><div>+</div><div>+/*</div><div>+ * Commutator: anyquery ~~ anyarray simply swaps the arguments.</div><div>+ */</div><div>+Datum</div><div>+anyquery_boolop_rev(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    AnyQuery   *q = PG_GETARG_ANYQUERY_P(0);</div><div>+    ArrayType  *arr = PG_GETARG_ARRAYTYPE_P(1);</div><div>+    Datum        result = do_boolop(fcinfo, arr, q);</div><div>+</div><div>+    PG_FREE_IF_COPY(q, 0);</div><div>+    PG_FREE_IF_COPY(arr, 1);</div><div>+    return result;</div><div>+}</div><div>diff --git a/contrib/anyarray/anyarray_gin.c b/contrib/anyarray/anyarray_gin.c</div><div>new file mode 100644</div><div>index 00000000000..d9d201c12d5</div><div>--- /dev/null</div><div>+++ b/contrib/anyarray/anyarray_gin.c</div><div>@@ -0,0 +1,374 @@</div><div>+/*-------------------------------------------------------------------------</div><div>+ *</div><div>+ * anyarray_gin.c</div><div>+ *        GIN opclasses that add the @@ (anyarray, anyquery) boolean search</div><div>+ *        operator to the existing array_ops behaviour.</div><div>+ *</div><div>+ * GIN's extractQuery support function doesn't see fn_expr, so the element</div><div>+ * type cannot be derived dynamically when the query is an anyquery (which</div><div>+ * carries only text tokens).  We work around this by exposing one opclass</div><div>+ * per concrete element type; each is a thin C wrapper that dispatches on</div><div>+ * the strategy number, delegating standard operators to inline replicas of</div><div>+ * core's array_ops behaviour and parsing anyquery tokens via the type's</div><div>+ * input function for strategy 5.</div><div>+ *</div><div>+ * Copyright (c) 2026, PostgreSQL Global Development Group</div><div>+ *</div><div>+ * IDENTIFICATION</div><div>+ *        contrib/anyarray/anyarray_gin.c</div><div>+ *</div><div>+ *-------------------------------------------------------------------------</div><div>+ */</div><div>+</div><div>+#include "postgres.h"</div><div>+</div><div>+#include "anyarray.h"</div><div>+</div><div>+#include "access/gin.h"</div><div>+#include "access/stratnum.h"</div><div>+#include "catalog/pg_type.h"</div><div>+#include "utils/array.h"</div><div>+#include "utils/builtins.h"</div><div>+#include "utils/lsyscache.h"</div><div>+</div><div>+PG_FUNCTION_INFO_V1(anyarray_gin_extract_query_int8);</div><div>+PG_FUNCTION_INFO_V1(anyarray_gin_extract_query_uuid);</div><div>+PG_FUNCTION_INFO_V1(anyarray_gin_extract_query_text);</div><div>+PG_FUNCTION_INFO_V1(anyarray_gin_consistent_int8);</div><div>+PG_FUNCTION_INFO_V1(anyarray_gin_consistent_uuid);</div><div>+PG_FUNCTION_INFO_V1(anyarray_gin_consistent_text);</div><div>+</div><div>+</div><div>+/* ------------------------------------------------------------------------</div><div>+ *  Common: extractQuery dispatcher</div><div>+ * ------------------------------------------------------------------------</div><div>+ */</div><div>+</div><div>+/*</div><div>+ * Extract array elements as GIN keys (used for strategies 1-4).</div><div>+ *</div><div>+ * Mirrors core's ginqueryarrayextract logic, but inlined so we don't depend</div><div>+ * on it being callable.  Returns a freshly-palloc'd Datum vector.</div><div>+ */</div><div>+static Datum *</div><div>+extract_array_keys(ArrayType *arr, AnyArrayTypeInfo *meta,</div><div>+                   int32 *nentries, bool **nulls_out)</div><div>+{<!-- --></div><div>+    Datum       *values;</div><div>+    bool       *nulls;</div><div>+    int            n;</div><div>+    int            i;</div><div>+    int            j = 0;</div><div>+</div><div>+    if (ARR_NDIM(arr) == 0)</div><div>+    {<!-- --></div><div>+        *nentries = 0;</div><div>+        *nulls_out = NULL;</div><div>+        return NULL;</div><div>+    }</div><div>+</div><div>+    deconstruct_array(arr, meta-&gt;element_type, meta-&gt;typlen,</div><div>+                      meta-&gt;typbyval, meta-&gt;typalign,</div><div>+                      &amp;values, &amp;nulls, &amp;n);</div><div>+</div><div>+    /* compact out NULL entries (we treat NULLs as never-present) */</div><div>+    for (i = 0; i &lt; n; i++)</div><div>+    {<!-- --></div><div>+        if (!nulls[i])</div><div>+        {<!-- --></div><div>+            if (j != i)</div><div>+            {<!-- --></div><div>+                values[j] = values[i];</div><div>+                nulls[j] = false;</div><div>+            }</div><div>+            j++;</div><div>+        }</div><div>+    }</div><div>+</div><div>+    *nentries = j;</div><div>+    *nulls_out = nulls;</div><div>+    return values;</div><div>+}</div><div>+</div><div>+/*</div><div>+ * Walk the anyquery: every VAL is a key that must be looked up in the GIN</div><div>+ * index.  Operators (&amp; | !) do not contribute keys.  Returns true if at</div><div>+ * least one VAL must be present for the query to possibly match (i.e. the</div><div>+ * query is not e.g. "!foo").</div><div>+ */</div><div>+static bool</div><div>+anyquery_has_required(AnyQuery *q, int idx)</div><div>+{<!-- --></div><div>+    AnyQueryItem *it;</div><div>+</div><div>+    if (idx &lt; 0)</div><div>+        return false;</div><div>+    it = &amp;q-&gt;items[idx];</div><div>+</div><div>+    if (it-&gt;type == ANYQ_VAL)</div><div>+        return true;</div><div>+    if (it-&gt;payload == ANYQ_NOT)</div><div>+        return false;            /* assume non-required under NOT */</div><div>+    if (it-&gt;payload == ANYQ_AND)</div><div>+        return anyquery_has_required(q, idx + it-&gt;left) ||</div><div>+            anyquery_has_required(q, idx - 1);</div><div>+    /* OR: both sides must contain required values */</div><div>+    return anyquery_has_required(q, idx + it-&gt;left) &amp;&amp;</div><div>+        anyquery_has_required(q, idx - 1);</div><div>+}</div><div>+</div><div>+static Datum</div><div>+do_gin_extract_query(FunctionCallInfo fcinfo, Oid elem_type)</div><div>+{<!-- --></div><div>+    Datum        queryDatum = PG_GETARG_DATUM(0);</div><div>+    int32       *nentries = (int32 *) PG_GETARG_POINTER(1);</div><div>+    StrategyNumber strat = PG_GETARG_UINT16(2);</div><div>+</div><div>+    /* PG_GETARG_POINTER(3): partial_matches -- not used */</div><div>+    /* PG_GETARG_POINTER(4): extra_data -- not used */</div><div>+    bool      **nullFlags = (bool **) PG_GETARG_POINTER(5);</div><div>+    int32       *searchMode = (int32 *) PG_GETARG_POINTER(6);</div><div>+    Datum       *keys = NULL;</div><div>+</div><div>+    *nentries = 0;</div><div>+    *nullFlags = NULL;</div><div>+    *searchMode = GIN_SEARCH_MODE_DEFAULT;</div><div>+</div><div>+    if (strat == ANYARRAY_GIN_BOOLEAN_STRATEGY)</div><div>+    {<!-- --></div><div>+        AnyQuery   *q = DatumGetAnyQueryP(queryDatum);</div><div>+        Oid            input_func;</div><div>+        Oid            input_typioparam;</div><div>+        int            i;</div><div>+        int            k = 0;</div><div>+</div><div>+        if (q-&gt;size &lt;= 0)</div><div>+            PG_RETURN_POINTER(NULL);</div><div>+</div><div>+        /*</div><div>+         * If the query has no required VAL (e.g. just "!foo"), we must scan</div><div>+         * the whole index because rows containing NONE of the queried values</div><div>+         * are valid matches.</div><div>+         */</div><div>+        if (!anyquery_has_required(q, q-&gt;size - 1))</div><div>+            *searchMode = GIN_SEARCH_MODE_ALL;</div><div>+</div><div>+        getTypeInputInfo(elem_type, &amp;input_func, &amp;input_typioparam);</div><div>+        keys = (Datum *) palloc(sizeof(Datum) * q-&gt;size);</div><div>+</div><div>+        for (i = 0; i &lt; q-&gt;size; i++)</div><div>+        {<!-- --></div><div>+            AnyQueryItem *it = &amp;q-&gt;items[i];</div><div>+</div><div>+            if (it-&gt;type != ANYQ_VAL)</div><div>+                continue;</div><div>+            keys[k++] = OidInputFunctionCall(input_func,</div><div>+                                             (char *) ANYQUERY_STRING(q, it),</div><div>+                                             input_typioparam, -1);</div><div>+        }</div><div>+        *nentries = k;</div><div>+        PG_RETURN_POINTER(keys);</div><div>+    }</div><div>+    else</div><div>+    {<!-- --></div><div>+        ArrayType  *arr = DatumGetArrayTypeP(queryDatum);</div><div>+        AnyArrayTypeInfo *meta = anyarray_get_meta(fcinfo, elem_type, false);</div><div>+        bool       *nulls;</div><div>+</div><div>+        ANYARRAY_CHECK_ARRAY(arr);</div><div>+        keys = extract_array_keys(arr, meta, nentries, &amp;nulls);</div><div>+</div><div>+        switch (strat)</div><div>+        {<!-- --></div><div>+            case ANYARRAY_GIN_OVERLAP_STRATEGY:</div><div>+                *searchMode = GIN_SEARCH_MODE_DEFAULT;</div><div>+                break;</div><div>+            case ANYARRAY_GIN_CONTAINED_STRATEGY:</div><div>+                *searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY;</div><div>+                break;</div><div>+            case ANYARRAY_GIN_EQUAL_STRATEGY:</div><div>+                *searchMode = (*nentries &gt; 0)</div><div>+                    ? GIN_SEARCH_MODE_DEFAULT</div><div>+                    : GIN_SEARCH_MODE_INCLUDE_EMPTY;</div><div>+                break;</div><div>+            case ANYARRAY_GIN_CONTAINS_STRATEGY:</div><div>+                *searchMode = (*nentries &gt; 0)</div><div>+                    ? GIN_SEARCH_MODE_DEFAULT</div><div>+                    : GIN_SEARCH_MODE_ALL;</div><div>+                break;</div><div>+            default:</div><div>+                elog(ERROR, "anyarray_gin: unknown strategy number: %d", strat);</div><div>+        }</div><div>+</div><div>+        (void) nulls;            /* swallowed by extract_array_keys */</div><div>+        PG_RETURN_POINTER(keys);</div><div>+    }</div><div>+}</div><div>+</div><div>+</div><div>+/* ------------------------------------------------------------------------</div><div>+ *  Common: consistent dispatcher</div><div>+ * ------------------------------------------------------------------------</div><div>+ */</div><div>+</div><div>+/*</div><div>+ * Evaluate an anyquery against an array of "key present" flags.  The i-th</div><div>+ * VAL in postfix order corresponds to check[i] (we mapped them in</div><div>+ * extractQuery, so the j-th VAL we emitted is check[j]).  We rebuild that</div><div>+ * VAL-only mapping here as we walk the postfix tree.</div><div>+ */</div><div>+typedef struct AnyQueryCheck</div><div>+{<!-- --></div><div>+    const bool *check;            /* GIN's present-key flags */</div><div>+    int            next;            /* next index in check[] */</div><div>+} AnyQueryCheck;</div><div>+</div><div>+static bool</div><div>+eval_with_check(AnyQuery *q, int idx, bool *vals)</div><div>+{<!-- --></div><div>+    AnyQueryItem *it = &amp;q-&gt;items[idx];</div><div>+</div><div>+    if (it-&gt;type == ANYQ_VAL)</div><div>+        return vals[idx];</div><div>+    if (it-&gt;payload == ANYQ_NOT)</div><div>+        return !eval_with_check(q, idx - 1, vals);</div><div>+    if (it-&gt;payload == ANYQ_AND)</div><div>+        return eval_with_check(q, idx + it-&gt;left, vals) &amp;&amp;</div><div>+            eval_with_check(q, idx - 1, vals);</div><div>+    /* OR */</div><div>+    return eval_with_check(q, idx + it-&gt;left, vals) ||</div><div>+        eval_with_check(q, idx - 1, vals);</div><div>+}</div><div>+</div><div>+static Datum</div><div>+do_gin_consistent(FunctionCallInfo fcinfo, Oid elem_type)</div><div>+{<!-- --></div><div>+    bool       *check = (bool *) PG_GETARG_POINTER(0);</div><div>+    StrategyNumber strat = PG_GETARG_UINT16(1);</div><div>+    Datum        queryDatum = PG_GETARG_DATUM(2);</div><div>+    int32        nkeys = PG_GETARG_INT32(3);</div><div>+</div><div>+    /* PG_GETARG_POINTER(4): extra_data -- not used */</div><div>+    bool       *recheck = (bool *) PG_GETARG_POINTER(5);</div><div>+    bool        result = false;</div><div>+    int            i;</div><div>+</div><div>+    (void) elem_type;</div><div>+</div><div>+    if (strat == ANYARRAY_GIN_BOOLEAN_STRATEGY)</div><div>+    {<!-- --></div><div>+        AnyQuery   *q = DatumGetAnyQueryP(queryDatum);</div><div>+        bool       *vals;</div><div>+        int            k = 0;</div><div>+</div><div>+        *recheck = false;</div><div>+</div><div>+        if (q-&gt;size &lt;= 0)</div><div>+            PG_RETURN_BOOL(false);</div><div>+</div><div>+        /* Map each VAL postfix slot to its position in check[]. */</div><div>+        vals = (bool *) palloc(sizeof(bool) * q-&gt;size);</div><div>+        for (i = 0; i &lt; q-&gt;size; i++)</div><div>+        {<!-- --></div><div>+            if (q-&gt;items[i].type == ANYQ_VAL)</div><div>+                vals[i] = check[k++];</div><div>+        }</div><div>+        result = eval_with_check(q, q-&gt;size - 1, vals);</div><div>+        pfree(vals);</div><div>+        PG_RETURN_BOOL(result);</div><div>+    }</div><div>+</div><div>+    switch (strat)</div><div>+    {<!-- --></div><div>+        case ANYARRAY_GIN_OVERLAP_STRATEGY:</div><div>+            *recheck = false;</div><div>+</div><div>+            /*</div><div>+             * GIN guarantees at least one true entry on entry; safe to say</div><div>+             * yes</div><div>+             */</div><div>+            for (i = 0; i &lt; nkeys; i++)</div><div>+            {<!-- --></div><div>+                if (check[i])</div><div>+                {<!-- --></div><div>+                    result = true;</div><div>+                    break;</div><div>+                }</div><div>+            }</div><div>+            break;</div><div>+        case ANYARRAY_GIN_CONTAINED_STRATEGY:</div><div>+            *recheck = true;</div><div>+            result = true;        /* must always recheck */</div><div>+            break;</div><div>+        case ANYARRAY_GIN_EQUAL_STRATEGY:</div><div>+            *recheck = true;</div><div>+            result = true;</div><div>+            for (i = 0; i &lt; nkeys; i++)</div><div>+            {<!-- --></div><div>+                if (!check[i])</div><div>+                {<!-- --></div><div>+                    result = false;</div><div>+                    break;</div><div>+                }</div><div>+            }</div><div>+            break;</div><div>+        case ANYARRAY_GIN_CONTAINS_STRATEGY:</div><div>+            *recheck = false;</div><div>+            result = true;</div><div>+            for (i = 0; i &lt; nkeys; i++)</div><div>+            {<!-- --></div><div>+                if (!check[i])</div><div>+                {<!-- --></div><div>+                    result = false;</div><div>+                    break;</div><div>+                }</div><div>+            }</div><div>+            break;</div><div>+        default:</div><div>+            elog(ERROR, "anyarray_gin: unknown strategy number: %d", strat);</div><div>+    }</div><div>+</div><div>+    PG_RETURN_BOOL(result);</div><div>+}</div><div>+</div><div>+</div><div>+/* ------------------------------------------------------------------------</div><div>+ *  Per-type wrappers</div><div>+ * ------------------------------------------------------------------------</div><div>+ */</div><div>+</div><div>+Datum</div><div>+anyarray_gin_extract_query_int8(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    return do_gin_extract_query(fcinfo, INT8OID);</div><div>+}</div><div>+</div><div>+Datum</div><div>+anyarray_gin_extract_query_uuid(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    return do_gin_extract_query(fcinfo, UUIDOID);</div><div>+}</div><div>+</div><div>+Datum</div><div>+anyarray_gin_extract_query_text(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    return do_gin_extract_query(fcinfo, TEXTOID);</div><div>+}</div><div>+</div><div>+Datum</div><div>+anyarray_gin_consistent_int8(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    return do_gin_consistent(fcinfo, INT8OID);</div><div>+}</div><div>+</div><div>+Datum</div><div>+anyarray_gin_consistent_uuid(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    return do_gin_consistent(fcinfo, UUIDOID);</div><div>+}</div><div>+</div><div>+Datum</div><div>+anyarray_gin_consistent_text(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    return do_gin_consistent(fcinfo, TEXTOID);</div><div>+}</div><div>diff --git a/contrib/anyarray/anyarray_gist.c b/contrib/anyarray/anyarray_gist.c</div><div>new file mode 100644</div><div>index 00000000000..89570c63ded</div><div>--- /dev/null</div><div>+++ b/contrib/anyarray/anyarray_gist.c</div><div>@@ -0,0 +1,742 @@</div><div>+/*-------------------------------------------------------------------------</div><div>+ *</div><div>+ * anyarray_gist.c</div><div>+ *        Signature-based GiST opclass for anyarray.</div><div>+ *</div><div>+ * Each indexed array is summarised as a fixed-size bit vector; each element</div><div>+ * contributes a single bit chosen by its hash modulo the signature length.</div><div>+ * Internal node keys are bitwise unions of their children, with an</div><div>+ * ALLISTRUE short-circuit when every bit would be set.</div><div>+ *</div><div>+ * The opclass supports the array operators &amp;&amp;, @&gt;, &lt;@, = and the anyarray</div><div>+ * extension's @@ operator.  Because signatures are lossy, all matches are</div><div>+ * rechecked by GiST.</div><div>+ *</div><div>+ * Copyright (c) 2026, PostgreSQL Global Development Group</div><div>+ *</div><div>+ * IDENTIFICATION</div><div>+ *        contrib/anyarray/anyarray_gist.c</div><div>+ *</div><div>+ *-------------------------------------------------------------------------</div><div>+ */</div><div>+</div><div>+#include "postgres.h"</div><div>+</div><div>+#include "anyarray.h"</div><div>+</div><div>+#include "access/gist.h"</div><div>+#include "access/reloptions.h"</div><div>+#include "access/stratnum.h"</div><div>+#include "catalog/pg_index.h"</div><div>+#include "catalog/pg_type.h"</div><div>+#include "miscadmin.h"</div><div>+#include "port/pg_bitutils.h"</div><div>+#include "utils/array.h"</div><div>+#include "utils/builtins.h"</div><div>+#include "utils/lsyscache.h"</div><div>+#include "utils/rel.h"</div><div>+</div><div>+/* Strategy numbers; share R-tree conventions where applicable. */</div><div>+#define ANYARRAY_OVERLAP_STRATEGY        3</div><div>+#define ANYARRAY_CONTAINS_STRATEGY        7</div><div>+#define ANYARRAY_CONTAINED_STRATEGY        8</div><div>+#define ANYARRAY_EQUAL_STRATEGY            18</div><div>+#define ANYARRAY_BOOLEAN_STRATEGY        20</div><div>+</div><div>+PG_FUNCTION_INFO_V1(anyarray_gist_key_in);</div><div>+PG_FUNCTION_INFO_V1(anyarray_gist_key_out);</div><div>+PG_FUNCTION_INFO_V1(anyarray_gist_consistent);</div><div>+PG_FUNCTION_INFO_V1(anyarray_gist_compress);</div><div>+PG_FUNCTION_INFO_V1(anyarray_gist_decompress);</div><div>+PG_FUNCTION_INFO_V1(anyarray_gist_union);</div><div>+PG_FUNCTION_INFO_V1(anyarray_gist_same);</div><div>+PG_FUNCTION_INFO_V1(anyarray_gist_penalty);</div><div>+PG_FUNCTION_INFO_V1(anyarray_gist_picksplit);</div><div>+PG_FUNCTION_INFO_V1(anyarray_gist_options);</div><div>+</div><div>+</div><div>+/* ------------------------------------------------------------------------</div><div>+ *  Storage type stubs</div><div>+ *</div><div>+ *  The signature key is only ever constructed internally by the index AM,</div><div>+ *  so its text input/output functions reject all calls (mirroring</div><div>+ *  intbig_gkey in contrib/intarray).</div><div>+ * ------------------------------------------------------------------------</div><div>+ */</div><div>+</div><div>+Datum</div><div>+anyarray_gist_key_in(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    ereport(ERROR,</div><div>+            (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),</div><div>+             errmsg("cannot accept a value of type %s",</div><div>+                    "anyarray_gist_key")));</div><div>+    PG_RETURN_VOID();</div><div>+}</div><div>+</div><div>+Datum</div><div>+anyarray_gist_key_out(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    ereport(ERROR,</div><div>+            (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),</div><div>+             errmsg("cannot display a value of type %s",</div><div>+                    "anyarray_gist_key")));</div><div>+    PG_RETURN_VOID();</div><div>+}</div><div>+</div><div>+</div><div>+/* ------------------------------------------------------------------------</div><div>+ *  Signature helpers</div><div>+ * ------------------------------------------------------------------------</div><div>+ */</div><div>+</div><div>+static AnyArrayGistKey *</div><div>+alloc_key(bool allistrue, int siglen, const unsigned char *src)</div><div>+{<!-- --></div><div>+    int32        flag = allistrue ? ANYARRAY_ALLISTRUE : 0;</div><div>+    Size        size = ANYARRAY_GKEY_SIZE(flag, siglen);</div><div>+    AnyArrayGistKey *k = (AnyArrayGistKey *) palloc(size);</div><div>+</div><div>+    SET_VARSIZE(k, size);</div><div>+    k-&gt;flag = flag;</div><div>+    if (!allistrue)</div><div>+    {<!-- --></div><div>+        if (src)</div><div>+            memcpy(k-&gt;data, src, siglen);</div><div>+        else</div><div>+            memset(k-&gt;data, 0, siglen);</div><div>+    }</div><div>+    return k;</div><div>+}</div><div>+</div><div>+/*</div><div>+ * Set the bit corresponding to "val" (a btree hash value) in "sig", a bit</div><div>+ * vector of length "siglen" bytes.</div><div>+ */</div><div>+static inline void</div><div>+set_bit(unsigned char *sig, uint32 hashval, int siglen)</div><div>+{<!-- --></div><div>+    uint32        bit = hashval % ((uint32) siglen * BITS_PER_BYTE);</div><div>+</div><div>+    sig[bit / BITS_PER_BYTE] |= (1U &lt;&lt; (bit % BITS_PER_BYTE));</div><div>+}</div><div>+</div><div>+static inline bool</div><div>+get_bit(const unsigned char *sig, uint32 hashval, int siglen)</div><div>+{<!-- --></div><div>+    uint32        bit = hashval % ((uint32) siglen * BITS_PER_BYTE);</div><div>+</div><div>+    return (sig[bit / BITS_PER_BYTE] &gt;&gt; (bit % BITS_PER_BYTE)) &amp; 1;</div><div>+}</div><div>+</div><div>+/*</div><div>+ * Hash a single Datum of the given element type, returning an unsigned 32-bit</div><div>+ * value suitable for indexing the bit vector.</div><div>+ */</div><div>+static uint32</div><div>+hash_elem(AnyArrayTypeInfo *meta, Datum value)</div><div>+{<!-- --></div><div>+    Datum        h = FunctionCall1Coll(&amp;meta-&gt;hash_proc, meta-&gt;typcollation,</div><div>+                                      value);</div><div>+</div><div>+    return (uint32) DatumGetInt32(h);</div><div>+}</div><div>+</div><div>+/*</div><div>+ * Hash each element of "arr" into "sig".  The metadata must have a valid</div><div>+ * hash_proc (use anyarray_get_meta(..., true)).</div><div>+ */</div><div>+static void</div><div>+hash_array_into(unsigned char *sig, int siglen,</div><div>+                ArrayType *arr, AnyArrayTypeInfo *meta)</div><div>+{<!-- --></div><div>+    Datum       *values;</div><div>+    bool       *nulls;</div><div>+    int            nelems;</div><div>+    int            i;</div><div>+</div><div>+    if (ARR_NDIM(arr) == 0)</div><div>+        return;</div><div>+</div><div>+    deconstruct_array(arr, meta-&gt;element_type, meta-&gt;typlen,</div><div>+                      meta-&gt;typbyval, meta-&gt;typalign,</div><div>+                      &amp;values, &amp;nulls, &amp;nelems);</div><div>+</div><div>+    for (i = 0; i &lt; nelems; i++)</div><div>+    {<!-- --></div><div>+        if (!nulls[i])</div><div>+            set_bit(sig, hash_elem(meta, values[i]), siglen);</div><div>+    }</div><div>+</div><div>+    pfree(values);</div><div>+    pfree(nulls);</div><div>+}</div><div>+</div><div>+/* Count "1" bits in a buffer of "n" bytes. */</div><div>+static int</div><div>+popcount_bytes(const unsigned char *p, int n)</div><div>+{<!-- --></div><div>+    return pg_popcount((const char *) p, n);</div><div>+}</div><div>+</div><div>+</div><div>+/* ------------------------------------------------------------------------</div><div>+ *  compress / decompress</div><div>+ * ------------------------------------------------------------------------</div><div>+ */</div><div>+</div><div>+Datum</div><div>+anyarray_gist_compress(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);</div><div>+    GISTENTRY  *retval = entry;</div><div>+    int            siglen = ANYARRAY_GET_SIGLEN();</div><div>+</div><div>+    if (entry-&gt;leafkey)</div><div>+    {<!-- --></div><div>+        ArrayType  *arr = DatumGetArrayTypeP(entry-&gt;key);</div><div>+        AnyArrayGistKey *key;</div><div>+        AnyArrayTypeInfo *meta;</div><div>+</div><div>+        ANYARRAY_CHECK_ARRAY(arr);</div><div>+</div><div>+        meta = anyarray_get_meta(fcinfo, ARR_ELEMTYPE(arr), true);</div><div>+</div><div>+        key = alloc_key(false, siglen, NULL);</div><div>+        hash_array_into(ANYARRAY_GKEY_SIGN(key), siglen, arr, meta);</div><div>+</div><div>+        retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));</div><div>+        gistentryinit(*retval, PointerGetDatum(key), entry-&gt;rel, entry-&gt;page,</div><div>+                      entry-&gt;offset, false);</div><div>+    }</div><div>+    else if (!ANYARRAY_GKEY_ISALLTRUE(DatumGetPointer(entry-&gt;key)))</div><div>+    {<!-- --></div><div>+        AnyArrayGistKey *k = (AnyArrayGistKey *) DatumGetPointer(entry-&gt;key);</div><div>+</div><div>+        /*</div><div>+         * If every bit happens to be set, switch to ALLISTRUE storage so</div><div>+         * subsequent operations don't have to compare a full bit vector.</div><div>+         */</div><div>+        if (popcount_bytes(ANYARRAY_GKEY_SIGN(k), siglen) ==</div><div>+            siglen * BITS_PER_BYTE)</div><div>+        {<!-- --></div><div>+            AnyArrayGistKey *r = alloc_key(true, siglen, NULL);</div><div>+</div><div>+            retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));</div><div>+            gistentryinit(*retval, PointerGetDatum(r), entry-&gt;rel, entry-&gt;page,</div><div>+                          entry-&gt;offset, false);</div><div>+        }</div><div>+    }</div><div>+</div><div>+    PG_RETURN_POINTER(retval);</div><div>+}</div><div>+</div><div>+Datum</div><div>+anyarray_gist_decompress(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    PG_RETURN_POINTER(PG_GETARG_POINTER(0));</div><div>+}</div><div>+</div><div>+</div><div>+/* ------------------------------------------------------------------------</div><div>+ *  union / same / penalty / picksplit / options</div><div>+ * ------------------------------------------------------------------------</div><div>+ */</div><div>+</div><div>+Datum</div><div>+anyarray_gist_union(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);</div><div>+    int           *sizep = (int *) PG_GETARG_POINTER(1);</div><div>+    int            siglen = ANYARRAY_GET_SIGLEN();</div><div>+    AnyArrayGistKey *out;</div><div>+    unsigned char *sig;</div><div>+    int            n = entryvec-&gt;n;</div><div>+    int            i;</div><div>+    bool        all = false;</div><div>+</div><div>+    out = alloc_key(false, siglen, NULL);</div><div>+    sig = ANYARRAY_GKEY_SIGN(out);</div><div>+</div><div>+    for (i = 0; i &lt; n; i++)</div><div>+    {<!-- --></div><div>+        AnyArrayGistKey *k = (AnyArrayGistKey *)</div><div>+            DatumGetPointer(entryvec-&gt;vector[i].key);</div><div>+</div><div>+        if (ANYARRAY_GKEY_ISALLTRUE(k))</div><div>+        {<!-- --></div><div>+            all = true;</div><div>+            break;</div><div>+        }</div><div>+        for (int j = 0; j &lt; siglen; j++)</div><div>+            sig[j] |= ANYARRAY_GKEY_SIGN(k)[j];</div><div>+    }</div><div>+</div><div>+    if (all || popcount_bytes(sig, siglen) == siglen * BITS_PER_BYTE)</div><div>+    {<!-- --></div><div>+        pfree(out);</div><div>+        out = alloc_key(true, siglen, NULL);</div><div>+    }</div><div>+</div><div>+    *sizep = VARSIZE(out);</div><div>+    PG_RETURN_POINTER(out);</div><div>+}</div><div>+</div><div>+Datum</div><div>+anyarray_gist_same(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    AnyArrayGistKey *a = (AnyArrayGistKey *) PG_GETARG_POINTER(0);</div><div>+    AnyArrayGistKey *b = (AnyArrayGistKey *) PG_GETARG_POINTER(1);</div><div>+    bool       *result = (bool *) PG_GETARG_POINTER(2);</div><div>+    int            siglen = ANYARRAY_GET_SIGLEN();</div><div>+</div><div>+    if (ANYARRAY_GKEY_ISALLTRUE(a) || ANYARRAY_GKEY_ISALLTRUE(b))</div><div>+        *result = ANYARRAY_GKEY_ISALLTRUE(a) &amp;&amp; ANYARRAY_GKEY_ISALLTRUE(b);</div><div>+    else</div><div>+        *result = (memcmp(ANYARRAY_GKEY_SIGN(a), ANYARRAY_GKEY_SIGN(b),</div><div>+                          siglen) == 0);</div><div>+</div><div>+    PG_RETURN_POINTER(result);</div><div>+}</div><div>+</div><div>+/*</div><div>+ * Hamming weight of (orig OR new) - Hamming weight of orig: the number of</div><div>+ * new bits a child would introduce.  ALLISTRUE entries have the maximum</div><div>+ * possible weight (siglen*8) so the answer is 0.</div><div>+ */</div><div>+Datum</div><div>+anyarray_gist_penalty(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    GISTENTRY  *origentry = (GISTENTRY *) PG_GETARG_POINTER(0);</div><div>+    GISTENTRY  *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);</div><div>+    float       *penalty = (float *) PG_GETARG_POINTER(2);</div><div>+    int            siglen = ANYARRAY_GET_SIGLEN();</div><div>+    AnyArrayGistKey *orig = (AnyArrayGistKey *) DatumGetPointer(origentry-&gt;key);</div><div>+    AnyArrayGistKey *new_ = (AnyArrayGistKey *) DatumGetPointer(newentry-&gt;key);</div><div>+</div><div>+    if (ANYARRAY_GKEY_ISALLTRUE(orig))</div><div>+    {<!-- --></div><div>+        *penalty = 0.0;</div><div>+    }</div><div>+    else if (ANYARRAY_GKEY_ISALLTRUE(new_))</div><div>+    {<!-- --></div><div>+        int            orig_bits = popcount_bytes(ANYARRAY_GKEY_SIGN(orig), siglen);</div><div>+</div><div>+        *penalty = (float) (siglen * BITS_PER_BYTE - orig_bits);</div><div>+    }</div><div>+    else</div><div>+    {<!-- --></div><div>+        unsigned char *o = ANYARRAY_GKEY_SIGN(orig);</div><div>+        unsigned char *n = ANYARRAY_GKEY_SIGN(new_);</div><div>+        int            added = 0;</div><div>+</div><div>+        for (int i = 0; i &lt; siglen; i++)</div><div>+        {<!-- --></div><div>+            unsigned char extra = n[i] &amp; ~o[i];</div><div>+</div><div>+            added += pg_number_of_ones[extra];</div><div>+        }</div><div>+        *penalty = (float) added;</div><div>+    }</div><div>+</div><div>+    PG_RETURN_POINTER(penalty);</div><div>+}</div><div>+</div><div>+/*</div><div>+ * Standard signature picksplit: sort entries by Hamming weight and split</div><div>+ * down the middle.  This isn't optimal but is correct and balanced; the</div><div>+ * fancier Guttman-style splits used by intbig can be added later.</div><div>+ */</div><div>+typedef struct PickSplitEntry</div><div>+{<!-- --></div><div>+    OffsetNumber offset;</div><div>+    int            weight;</div><div>+} PickSplitEntry;</div><div>+</div><div>+static int</div><div>+psplit_cmp(const void *a, const void *b)</div><div>+{<!-- --></div><div>+    int            wa = ((const PickSplitEntry *) a)-&gt;weight;</div><div>+    int            wb = ((const PickSplitEntry *) b)-&gt;weight;</div><div>+</div><div>+    return (wa &gt; wb) - (wa &lt; wb);</div><div>+}</div><div>+</div><div>+static void</div><div>+or_into(unsigned char *dst, const unsigned char *src, int siglen)</div><div>+{<!-- --></div><div>+    for (int i = 0; i &lt; siglen; i++)</div><div>+        dst[i] |= src[i];</div><div>+}</div><div>+</div><div>+Datum</div><div>+anyarray_gist_picksplit(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);</div><div>+    GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);</div><div>+    int            siglen = ANYARRAY_GET_SIGLEN();</div><div>+    int            n = entryvec-&gt;n - 1;    /* entries start at index 1 */</div><div>+    PickSplitEntry *items;</div><div>+    AnyArrayGistKey *left,</div><div>+               *right;</div><div>+    int            i;</div><div>+    int            split;</div><div>+</div><div>+    items = (PickSplitEntry *) palloc(n * sizeof(PickSplitEntry));</div><div>+    for (i = 0; i &lt; n; i++)</div><div>+    {<!-- --></div><div>+        AnyArrayGistKey *k = (AnyArrayGistKey *)</div><div>+            DatumGetPointer(entryvec-&gt;vector[i + 1].key);</div><div>+</div><div>+        items[i].offset = (OffsetNumber) (i + 1);</div><div>+        items[i].weight = ANYARRAY_GKEY_ISALLTRUE(k)</div><div>+            ? siglen * BITS_PER_BYTE</div><div>+            : popcount_bytes(ANYARRAY_GKEY_SIGN(k), siglen);</div><div>+    }</div><div>+    qsort(items, n, sizeof(PickSplitEntry), psplit_cmp);</div><div>+</div><div>+    v-&gt;spl_left = (OffsetNumber *) palloc(n * sizeof(OffsetNumber));</div><div>+    v-&gt;spl_right = (OffsetNumber *) palloc(n * sizeof(OffsetNumber));</div><div>+    v-&gt;spl_nleft = 0;</div><div>+    v-&gt;spl_nright = 0;</div><div>+    left = alloc_key(false, siglen, NULL);</div><div>+    right = alloc_key(false, siglen, NULL);</div><div>+</div><div>+    split = n / 2;</div><div>+    if (split == 0)</div><div>+        split = 1;</div><div>+    if (split == n)</div><div>+        split = n - 1;</div><div>+</div><div>+    for (i = 0; i &lt; split; i++)</div><div>+    {<!-- --></div><div>+        AnyArrayGistKey *k = (AnyArrayGistKey *)</div><div>+            DatumGetPointer(entryvec-&gt;vector[items[i].offset].key);</div><div>+</div><div>+        v-&gt;spl_left[v-&gt;spl_nleft++] = items[i].offset;</div><div>+        if (ANYARRAY_GKEY_ISALLTRUE(k))</div><div>+        {<!-- --></div><div>+            pfree(left);</div><div>+            left = alloc_key(true, siglen, NULL);</div><div>+        }</div><div>+        else if (!ANYARRAY_GKEY_ISALLTRUE(left))</div><div>+            or_into(ANYARRAY_GKEY_SIGN(left), ANYARRAY_GKEY_SIGN(k), siglen);</div><div>+    }</div><div>+    for (; i &lt; n; i++)</div><div>+    {<!-- --></div><div>+        AnyArrayGistKey *k = (AnyArrayGistKey *)</div><div>+            DatumGetPointer(entryvec-&gt;vector[items[i].offset].key);</div><div>+</div><div>+        v-&gt;spl_right[v-&gt;spl_nright++] = items[i].offset;</div><div>+        if (ANYARRAY_GKEY_ISALLTRUE(k))</div><div>+        {<!-- --></div><div>+            pfree(right);</div><div>+            right = alloc_key(true, siglen, NULL);</div><div>+        }</div><div>+        else if (!ANYARRAY_GKEY_ISALLTRUE(right))</div><div>+            or_into(ANYARRAY_GKEY_SIGN(right), ANYARRAY_GKEY_SIGN(k), siglen);</div><div>+    }</div><div>+</div><div>+    v-&gt;spl_ldatum = PointerGetDatum(left);</div><div>+    v-&gt;spl_rdatum = PointerGetDatum(right);</div><div>+</div><div>+    pfree(items);</div><div>+    PG_RETURN_POINTER(v);</div><div>+}</div><div>+</div><div>+/* opclass options: just the signature length, in bytes */</div><div>+static void</div><div>+fill_siglen_default(int *siglen)</div><div>+{<!-- --></div><div>+    *siglen = ANYARRAY_SIGLEN_DEFAULT;</div><div>+}</div><div>+</div><div>+Datum</div><div>+anyarray_gist_options(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    local_relopts *relopts = (local_relopts *) PG_GETARG_POINTER(0);</div><div>+</div><div>+    init_local_reloptions(relopts, sizeof(AnyArrayGistOptions));</div><div>+    add_local_int_reloption(relopts, "siglen",</div><div>+                            "signature length in bytes",</div><div>+                            ANYARRAY_SIGLEN_DEFAULT, 1, ANYARRAY_SIGLEN_MAX,</div><div>+                            offsetof(AnyArrayGistOptions, siglen));</div><div>+</div><div>+    (void) fill_siglen_default;</div><div>+    PG_RETURN_VOID();</div><div>+}</div><div>+</div><div>+</div><div>+/* ------------------------------------------------------------------------</div><div>+ *  consistent</div><div>+ * ------------------------------------------------------------------------</div><div>+ */</div><div>+</div><div>+/*</div><div>+ * For overlap: any single matching bit means the key MIGHT contain something</div><div>+ * the query references.  Returns true if at least one element of "query"</div><div>+ * hashes to a set bit in "sig"; ALLISTRUE keys trivially pass.</div><div>+ */</div><div>+static bool</div><div>+sig_overlap_array(const unsigned char *sig, int siglen,</div><div>+                  ArrayType *query, AnyArrayTypeInfo *meta)</div><div>+{<!-- --></div><div>+    Datum       *values;</div><div>+    bool       *nulls;</div><div>+    int            nelems;</div><div>+    int            i;</div><div>+    bool        found = false;</div><div>+</div><div>+    if (ARR_NDIM(query) == 0)</div><div>+        return false;</div><div>+</div><div>+    deconstruct_array(query, meta-&gt;element_type, meta-&gt;typlen,</div><div>+                      meta-&gt;typbyval, meta-&gt;typalign,</div><div>+                      &amp;values, &amp;nulls, &amp;nelems);</div><div>+</div><div>+    for (i = 0; i &lt; nelems; i++)</div><div>+    {<!-- --></div><div>+        if (nulls[i])</div><div>+            continue;</div><div>+        if (get_bit(sig, hash_elem(meta, values[i]), siglen))</div><div>+        {<!-- --></div><div>+            found = true;</div><div>+            break;</div><div>+        }</div><div>+    }</div><div>+    pfree(values);</div><div>+    pfree(nulls);</div><div>+    return found;</div><div>+}</div><div>+</div><div>+/*</div><div>+ * For contains: every element of the query must hash to a set bit.</div><div>+ * If any required bit is missing the key cannot contain the query.</div><div>+ */</div><div>+static bool</div><div>+sig_contains_array(const unsigned char *sig, int siglen,</div><div>+                   ArrayType *query, AnyArrayTypeInfo *meta)</div><div>+{<!-- --></div><div>+    Datum       *values;</div><div>+    bool       *nulls;</div><div>+    int            nelems;</div><div>+    int            i;</div><div>+    bool        ok = true;</div><div>+</div><div>+    if (ARR_NDIM(query) == 0)</div><div>+        return true;</div><div>+</div><div>+    deconstruct_array(query, meta-&gt;element_type, meta-&gt;typlen,</div><div>+                      meta-&gt;typbyval, meta-&gt;typalign,</div><div>+                      &amp;values, &amp;nulls, &amp;nelems);</div><div>+</div><div>+    for (i = 0; i &lt; nelems; i++)</div><div>+    {<!-- --></div><div>+        if (nulls[i])</div><div>+            continue;</div><div>+        if (!get_bit(sig, hash_elem(meta, values[i]), siglen))</div><div>+        {<!-- --></div><div>+            ok = false;</div><div>+            break;</div><div>+        }</div><div>+    }</div><div>+    pfree(values);</div><div>+    pfree(nulls);</div><div>+    return ok;</div><div>+}</div><div>+</div><div>+/*</div><div>+ * Recursive postfix evaluator for sig_eval_query().</div><div>+ *</div><div>+ * "vals" holds the precomputed signature lookup for every VAL slot.  NOT</div><div>+ * is non-restrictive under a signature (the bit could still be set by some</div><div>+ * other inserted array), so we conservatively report true on negation; the</div><div>+ * GiST recheck step will then filter on the real values.</div><div>+ */</div><div>+static bool</div><div>+sig_eval_walk(AnyQuery *q, int idx, const bool *vals)</div><div>+{<!-- --></div><div>+    AnyQueryItem *it;</div><div>+</div><div>+    check_stack_depth();</div><div>+    Assert(idx &gt;= 0);</div><div>+    it = &amp;q-&gt;items[idx];</div><div>+</div><div>+    if (it-&gt;type == ANYQ_VAL)</div><div>+        return vals[idx];</div><div>+    if (it-&gt;payload == ANYQ_NOT)</div><div>+        return true;</div><div>+    if (it-&gt;payload == ANYQ_AND)</div><div>+        return sig_eval_walk(q, idx + it-&gt;left, vals) &amp;&amp;</div><div>+            sig_eval_walk(q, idx - 1, vals);</div><div>+    /* ANYQ_OR */</div><div>+    return sig_eval_walk(q, idx + it-&gt;left, vals) ||</div><div>+        sig_eval_walk(q, idx - 1, vals);</div><div>+}</div><div>+</div><div>+/*</div><div>+ * Evaluate an anyquery against a signature.  Each VAL is parsed using the</div><div>+ * element type's text input, hashed, then looked up in the signature.</div><div>+ */</div><div>+static bool</div><div>+sig_eval_query(const unsigned char *sig, int siglen,</div><div>+               AnyQuery *q, AnyArrayTypeInfo *meta,</div><div>+               Oid input_func, Oid input_typioparam)</div><div>+{<!-- --></div><div>+    bool       *vals;</div><div>+    bool        result;</div><div>+    int            i;</div><div>+</div><div>+    if (q-&gt;size &lt;= 0)</div><div>+        return false;</div><div>+</div><div>+    vals = (bool *) palloc0(sizeof(bool) * q-&gt;size);</div><div>+</div><div>+    for (i = 0; i &lt; q-&gt;size; i++)</div><div>+    {<!-- --></div><div>+        AnyQueryItem *it = &amp;q-&gt;items[i];</div><div>+        Datum        v;</div><div>+</div><div>+        if (it-&gt;type != ANYQ_VAL)</div><div>+            continue;</div><div>+        v = OidInputFunctionCall(input_func,</div><div>+                                 (char *) ANYQUERY_STRING(q, it),</div><div>+                                 input_typioparam, -1);</div><div>+        vals[i] = get_bit(sig, hash_elem(meta, v), siglen);</div><div>+    }</div><div>+</div><div>+    result = sig_eval_walk(q, q-&gt;size - 1, vals);</div><div>+    pfree(vals);</div><div>+    return result;</div><div>+}</div><div>+</div><div>+Datum</div><div>+anyarray_gist_consistent(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);</div><div>+    StrategyNumber strat = (StrategyNumber) PG_GETARG_UINT16(2);</div><div>+    Oid            subtype = PG_GETARG_OID(3);</div><div>+    bool       *recheck = (bool *) PG_GETARG_POINTER(4);</div><div>+    AnyArrayGistKey *key = (AnyArrayGistKey *) DatumGetPointer(entry-&gt;key);</div><div>+    int            siglen = ANYARRAY_GET_SIGLEN();</div><div>+    bool        result;</div><div>+</div><div>+    /* All signature-based answers require a recheck. */</div><div>+    *recheck = true;</div><div>+</div><div>+    if (ANYARRAY_GKEY_ISALLTRUE(key))</div><div>+    {<!-- --></div><div>+        /* Cannot prune anything from an all-true signature. */</div><div>+        PG_RETURN_BOOL(true);</div><div>+    }</div><div>+</div><div>+    (void) subtype;</div><div>+</div><div>+    if (strat == ANYARRAY_BOOLEAN_STRATEGY)</div><div>+    {<!-- --></div><div>+        AnyQuery   *q = PG_GETARG_ANYQUERY_P(1);</div><div>+        AnyArrayTypeInfo *meta;</div><div>+        Form_pg_index ind;</div><div>+        Oid            coltype;</div><div>+        Oid            elemtype;</div><div>+        Oid            input_func;</div><div>+        Oid            input_typioparam;</div><div>+</div><div>+        /*</div><div>+         * The query is anyquery, so we recover the element type from the</div><div>+         * indexed column's pg_index entry.  The index's own rd_att gives the</div><div>+         * STORAGE type (anyarray_gist_key), not the original array type, so</div><div>+         * we read the indrelid + indkey instead.</div><div>+         */</div><div>+        ind = entry-&gt;rel-&gt;rd_index;</div><div>+        if (ind == NULL || ind-&gt;indnatts &lt; 1)</div><div>+            ereport(ERROR,</div><div>+                    (errcode(ERRCODE_INTERNAL_ERROR),</div><div>+                     errmsg("anyarray GiST index has no key column")));</div><div>+        coltype = get_atttype(ind-&gt;indrelid, ind-&gt;indkey.values[0]);</div><div>+        elemtype = get_element_type(coltype);</div><div>+        if (!OidIsValid(elemtype))</div><div>+            ereport(ERROR,</div><div>+                    (errcode(ERRCODE_DATATYPE_MISMATCH),</div><div>+                     errmsg("cannot determine element type for anyquery match")));</div><div>+</div><div>+        meta = anyarray_get_meta(fcinfo, elemtype, true);</div><div>+        getTypeInputInfo(elemtype, &amp;input_func, &amp;input_typioparam);</div><div>+</div><div>+        result = sig_eval_query(ANYARRAY_GKEY_SIGN(key), siglen, q, meta,</div><div>+                                input_func, input_typioparam);</div><div>+        PG_FREE_IF_COPY(q, 1);</div><div>+        PG_RETURN_BOOL(result);</div><div>+    }</div><div>+    else</div><div>+    {<!-- --></div><div>+        ArrayType  *query = PG_GETARG_ARRAYTYPE_P(1);</div><div>+        AnyArrayTypeInfo *meta;</div><div>+</div><div>+        ANYARRAY_CHECK_ARRAY(query);</div><div>+        meta = anyarray_get_meta(fcinfo, ARR_ELEMTYPE(query), true);</div><div>+</div><div>+        switch (strat)</div><div>+        {<!-- --></div><div>+            case ANYARRAY_OVERLAP_STRATEGY:</div><div>+                result = sig_overlap_array(ANYARRAY_GKEY_SIGN(key), siglen,</div><div>+                                           query, meta);</div><div>+                break;</div><div>+            case ANYARRAY_CONTAINS_STRATEGY:</div><div>+                result = sig_contains_array(ANYARRAY_GKEY_SIGN(key), siglen,</div><div>+                                            query, meta);</div><div>+                break;</div><div>+            case ANYARRAY_CONTAINED_STRATEGY:</div><div>+</div><div>+                /*</div><div>+                 * For "key &lt;@ query", signatures cannot exclude a non-leaf</div><div>+                 * key because its bits may come from many distinct children</div><div>+                 * which need not individually be contained in query. Always</div><div>+                 * recheck.</div><div>+                 */</div><div>+                if (GIST_LEAF(entry))</div><div>+                {<!-- --></div><div>+                    /*</div><div>+                     * At the leaf, every set bit must also have been set by</div><div>+                     * the query (i.e., element hashes to that bit).</div><div>+                     */</div><div>+                    unsigned char *qsig;</div><div>+                    int            i;</div><div>+</div><div>+                    qsig = (unsigned char *) palloc0(siglen);</div><div>+                    hash_array_into(qsig, siglen, query, meta);</div><div>+                    result = true;</div><div>+                    for (i = 0; i &lt; siglen; i++)</div><div>+                    {<!-- --></div><div>+                        if (ANYARRAY_GKEY_SIGN(key)[i] &amp; ~qsig[i])</div><div>+                        {<!-- --></div><div>+                            result = false;</div><div>+                            break;</div><div>+                        }</div><div>+                    }</div><div>+                    pfree(qsig);</div><div>+                }</div><div>+                else</div><div>+                    result = true;</div><div>+                break;</div><div>+            case ANYARRAY_EQUAL_STRATEGY:</div><div>+</div><div>+                /*</div><div>+                 * The leaf signature for an equal row contains every bit of</div><div>+                 * the query's hash; internal unions contain at least those</div><div>+                 * bits.  So "key contains query bits" is a sound</div><div>+                 * over-approximation that recheck will tighten.</div><div>+                 */</div><div>+                result = sig_contains_array(ANYARRAY_GKEY_SIGN(key), siglen,</div><div>+                                            query, meta);</div><div>+                break;</div><div>+            default:</div><div>+                elog(ERROR, "unrecognized strategy number: %d", strat);</div><div>+                result = false;</div><div>+                break;</div><div>+        }</div><div>+</div><div>+        PG_FREE_IF_COPY(query, 1);</div><div>+        PG_RETURN_BOOL(result);</div><div>+    }</div><div>+}</div><div>diff --git a/contrib/anyarray/anyarray_op.c b/contrib/anyarray/anyarray_op.c</div><div>new file mode 100644</div><div>index 00000000000..47a050bb0e3</div><div>--- /dev/null</div><div>+++ b/contrib/anyarray/anyarray_op.c</div><div>@@ -0,0 +1,613 @@</div><div>+/*-------------------------------------------------------------------------</div><div>+ *</div><div>+ * anyarray_op.c</div><div>+ *        Set-style operations on arrays of any type.</div><div>+ *</div><div>+ * All functions accept anyarray / anyelement inputs and dispatch to the</div><div>+ * element type's btree comparison function through anyarray_get_meta().</div><div>+ * The operations mirror the corresponding intarray operations but are</div><div>+ * type-polymorphic.</div><div>+ *</div><div>+ * Copyright (c) 2026, PostgreSQL Global Development Group</div><div>+ *</div><div>+ * IDENTIFICATION</div><div>+ *        contrib/anyarray/anyarray_op.c</div><div>+ *</div><div>+ *-------------------------------------------------------------------------</div><div>+ */</div><div>+</div><div>+#include "postgres.h"</div><div>+</div><div>+#include "anyarray.h"</div><div>+</div><div>+#include "catalog/pg_type.h"</div><div>+#include "lib/qunique.h"</div><div>+#include "utils/array.h"</div><div>+#include "utils/builtins.h"</div><div>+#include "utils/lsyscache.h"</div><div>+</div><div>+</div><div>+/*</div><div>+ * deconstruct_arr_meta</div><div>+ *        Pull element values out of "arr" and fill in "*meta" for its type.</div><div>+ *</div><div>+ * Returns Datum array in *out_values (palloc'd), count in *out_nelems.  The</div><div>+ * input array must already have passed ANYARRAY_CHECK_ARRAY; we still gate</div><div>+ * on it defensively because all entry points feed through this helper.</div><div>+ */</div><div>+static void</div><div>+deconstruct_arr_meta(FunctionCallInfo fcinfo, ArrayType *arr,</div><div>+                     AnyArrayTypeInfo **out_meta,</div><div>+                     Datum **out_values, int *out_nelems)</div><div>+{<!-- --></div><div>+    AnyArrayTypeInfo *meta;</div><div>+    Datum       *values;</div><div>+    bool       *nulls;</div><div>+    int            nelems;</div><div>+</div><div>+    ANYARRAY_CHECK_ARRAY(arr);</div><div>+</div><div>+    meta = anyarray_get_meta(fcinfo, ARR_ELEMTYPE(arr), false);</div><div>+</div><div>+    if (ARR_NDIM(arr) == 0)</div><div>+    {<!-- --></div><div>+        *out_meta = meta;</div><div>+        *out_values = NULL;</div><div>+        *out_nelems = 0;</div><div>+        return;</div><div>+    }</div><div>+</div><div>+    deconstruct_array(arr, meta-&gt;element_type,</div><div>+                      meta-&gt;typlen, meta-&gt;typbyval, meta-&gt;typalign,</div><div>+                      &amp;values, &amp;nulls, &amp;nelems);</div><div>+    pfree(nulls);                /* we've already rejected nulls above */</div><div>+</div><div>+    *out_meta = meta;</div><div>+    *out_values = values;</div><div>+    *out_nelems = nelems;</div><div>+}</div><div>+</div><div>+/*</div><div>+ * make_array_from_datums</div><div>+ *        Build a 1-D array from the given Datum vector.  Empty -&gt; empty array.</div><div>+ */</div><div>+static ArrayType *</div><div>+make_array_from_datums(Datum *values, int nelems, AnyArrayTypeInfo *meta)</div><div>+{<!-- --></div><div>+    if (nelems == 0)</div><div>+        return construct_empty_array(meta-&gt;element_type);</div><div>+</div><div>+    return construct_array(values, nelems, meta-&gt;element_type,</div><div>+                           meta-&gt;typlen, meta-&gt;typbyval, meta-&gt;typalign);</div><div>+}</div><div>+</div><div>+</div><div>+/* ------------------------------------------------------------------------</div><div>+ *  sort / uniq</div><div>+ * ------------------------------------------------------------------------</div><div>+ */</div><div>+</div><div>+PG_FUNCTION_INFO_V1(anyarray_sort);</div><div>+PG_FUNCTION_INFO_V1(anyarray_sort_dir);</div><div>+PG_FUNCTION_INFO_V1(anyarray_uniq);</div><div>+</div><div>+/*</div><div>+ * Sort an array ascending.</div><div>+ */</div><div>+Datum</div><div>+anyarray_sort(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    ArrayType  *arr = PG_GETARG_ARRAYTYPE_P(0);</div><div>+    AnyArrayTypeInfo *meta;</div><div>+    Datum       *values;</div><div>+    int            nelems;</div><div>+</div><div>+    deconstruct_arr_meta(fcinfo, arr, &amp;meta, &amp;values, &amp;nelems);</div><div>+</div><div>+    if (nelems &gt; 1)</div><div>+        qsort_arg(values, nelems, sizeof(Datum), anyarray_cmp_datum, meta);</div><div>+</div><div>+    PG_RETURN_ARRAYTYPE_P(make_array_from_datums(values, nelems, meta));</div><div>+}</div><div>+</div><div>+/*</div><div>+ * Sort an array.  The direction text is case-insensitive and must be one of</div><div>+ * 'asc' / 'ascending' or 'desc' / 'descending'.</div><div>+ */</div><div>+Datum</div><div>+anyarray_sort_dir(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    ArrayType  *arr = PG_GETARG_ARRAYTYPE_P(0);</div><div>+    text       *dir = PG_GETARG_TEXT_PP(1);</div><div>+    const char *dirstr = VARDATA_ANY(dir);</div><div>+    int            dirlen = VARSIZE_ANY_EXHDR(dir);</div><div>+    bool        ascending;</div><div>+    AnyArrayTypeInfo *meta;</div><div>+    Datum       *values;</div><div>+    int            nelems;</div><div>+</div><div>+    if ((dirlen == 3 &amp;&amp; pg_strncasecmp(dirstr, "asc", 3) == 0) ||</div><div>+        (dirlen == 9 &amp;&amp; pg_strncasecmp(dirstr, "ascending", 9) == 0))</div><div>+        ascending = true;</div><div>+    else if ((dirlen == 4 &amp;&amp; pg_strncasecmp(dirstr, "desc", 4) == 0) ||</div><div>+             (dirlen == 10 &amp;&amp; pg_strncasecmp(dirstr, "descending", 10) == 0))</div><div>+        ascending = false;</div><div>+    else</div><div>+        ereport(ERROR,</div><div>+                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),</div><div>+                 errmsg("second parameter must be \"asc\" or \"desc\"")));</div><div>+</div><div>+    deconstruct_arr_meta(fcinfo, arr, &amp;meta, &amp;values, &amp;nelems);</div><div>+</div><div>+    if (nelems &gt; 1)</div><div>+    {<!-- --></div><div>+        qsort_arg(values, nelems, sizeof(Datum), anyarray_cmp_datum, meta);</div><div>+        if (!ascending)</div><div>+        {<!-- --></div><div>+            Datum       *l = values;</div><div>+            Datum       *r = values + nelems - 1;</div><div>+</div><div>+            while (l &lt; r)</div><div>+            {<!-- --></div><div>+                Datum        tmp = *l;</div><div>+</div><div>+                *l++ = *r;</div><div>+                *r-- = tmp;</div><div>+            }</div><div>+        }</div><div>+    }</div><div>+</div><div>+    PG_RETURN_ARRAYTYPE_P(make_array_from_datums(values, nelems, meta));</div><div>+}</div><div>+</div><div>+/*</div><div>+ * Remove duplicate elements; does not require pre-sorted input.</div><div>+ */</div><div>+Datum</div><div>+anyarray_uniq(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    ArrayType  *arr = PG_GETARG_ARRAYTYPE_P(0);</div><div>+    AnyArrayTypeInfo *meta;</div><div>+    Datum       *values;</div><div>+    int            nelems;</div><div>+    int            nunique;</div><div>+</div><div>+    deconstruct_arr_meta(fcinfo, arr, &amp;meta, &amp;values, &amp;nelems);</div><div>+</div><div>+    if (nelems &gt; 1)</div><div>+    {<!-- --></div><div>+        qsort_arg(values, nelems, sizeof(Datum), anyarray_cmp_datum, meta);</div><div>+        nunique = qunique_arg(values, nelems, sizeof(Datum),</div><div>+                              anyarray_cmp_datum, meta);</div><div>+    }</div><div>+    else</div><div>+        nunique = nelems;</div><div>+</div><div>+    PG_RETURN_ARRAYTYPE_P(make_array_from_datums(values, nunique, meta));</div><div>+}</div><div>+</div><div>+</div><div>+/* ------------------------------------------------------------------------</div><div>+ *  idx / subarray / cardinality</div><div>+ * ------------------------------------------------------------------------</div><div>+ */</div><div>+</div><div>+PG_FUNCTION_INFO_V1(anyarray_idx);</div><div>+PG_FUNCTION_INFO_V1(anyarray_subarray);</div><div>+PG_FUNCTION_INFO_V1(anyarray_subarray_to_end);</div><div>+PG_FUNCTION_INFO_V1(anyarray_icount);</div><div>+</div><div>+/*</div><div>+ * Return the 1-based index of the first occurrence of "elem" in "arr",</div><div>+ * or 0 if not found.</div><div>+ */</div><div>+Datum</div><div>+anyarray_idx(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    ArrayType  *arr = PG_GETARG_ARRAYTYPE_P(0);</div><div>+    Datum        elem = PG_GETARG_DATUM(1);</div><div>+    AnyArrayTypeInfo *meta;</div><div>+    Datum       *values;</div><div>+    int            nelems;</div><div>+    int            i;</div><div>+</div><div>+    deconstruct_arr_meta(fcinfo, arr, &amp;meta, &amp;values, &amp;nelems);</div><div>+</div><div>+    for (i = 0; i &lt; nelems; i++)</div><div>+    {<!-- --></div><div>+        Datum        eq = FunctionCall2Coll(&amp;meta-&gt;eq_proc, meta-&gt;typcollation,</div><div>+                                           values[i], elem);</div><div>+</div><div>+        if (DatumGetBool(eq))</div><div>+            PG_RETURN_INT32(i + 1);</div><div>+    }</div><div>+</div><div>+    PG_RETURN_INT32(0);</div><div>+}</div><div>+</div><div>+/*</div><div>+ * Common subarray extraction.  "start" is 1-based; if it is non-positive</div><div>+ * the function returns an empty array.  "len" gives the maximum number of</div><div>+ * elements to copy; if "have_len" is false the whole tail is returned.</div><div>+ */</div><div>+static ArrayType *</div><div>+do_subarray(FunctionCallInfo fcinfo, ArrayType *arr,</div><div>+            int32 start, int32 len, bool have_len)</div><div>+{<!-- --></div><div>+    AnyArrayTypeInfo *meta;</div><div>+    Datum       *values;</div><div>+    int            nelems;</div><div>+    int            off;</div><div>+    int            n;</div><div>+</div><div>+    deconstruct_arr_meta(fcinfo, arr, &amp;meta, &amp;values, &amp;nelems);</div><div>+</div><div>+    if (start &lt; 1 || start &gt; nelems)</div><div>+        return construct_empty_array(meta-&gt;element_type);</div><div>+</div><div>+    off = start - 1;</div><div>+    if (have_len)</div><div>+    {<!-- --></div><div>+        if (len &lt;= 0)</div><div>+            return construct_empty_array(meta-&gt;element_type);</div><div>+        n = Min(len, nelems - off);</div><div>+    }</div><div>+    else</div><div>+        n = nelems - off;</div><div>+</div><div>+    return make_array_from_datums(values + off, n, meta);</div><div>+}</div><div>+</div><div>+/*</div><div>+ * subarray(arr, start, len)</div><div>+ */</div><div>+Datum</div><div>+anyarray_subarray(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    ArrayType  *arr = PG_GETARG_ARRAYTYPE_P(0);</div><div>+    int32        start = PG_GETARG_INT32(1);</div><div>+    int32        len = PG_GETARG_INT32(2);</div><div>+</div><div>+    PG_RETURN_ARRAYTYPE_P(do_subarray(fcinfo, arr, start, len, true));</div><div>+}</div><div>+</div><div>+/*</div><div>+ * subarray(arr, start) -- to end</div><div>+ */</div><div>+Datum</div><div>+anyarray_subarray_to_end(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    ArrayType  *arr = PG_GETARG_ARRAYTYPE_P(0);</div><div>+    int32        start = PG_GETARG_INT32(1);</div><div>+</div><div>+    PG_RETURN_ARRAYTYPE_P(do_subarray(fcinfo, arr, start, 0, false));</div><div>+}</div><div>+</div><div>+/*</div><div>+ * icount: total element count, intarray-style.  This duplicates</div><div>+ * built-in cardinality() but we expose it under the # operator the way</div><div>+ * intarray does.</div><div>+ */</div><div>+Datum</div><div>+anyarray_icount(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    ArrayType  *arr = PG_GETARG_ARRAYTYPE_P(0);</div><div>+</div><div>+    ANYARRAY_CHECK_ARRAY(arr);</div><div>+    PG_RETURN_INT32(ANYARRAY_NELEMS(arr));</div><div>+}</div><div>+</div><div>+</div><div>+/* ------------------------------------------------------------------------</div><div>+ *  intersect / union / difference</div><div>+ * ------------------------------------------------------------------------</div><div>+ */</div><div>+</div><div>+PG_FUNCTION_INFO_V1(anyarray_intersect);</div><div>+PG_FUNCTION_INFO_V1(anyarray_union);</div><div>+PG_FUNCTION_INFO_V1(anyarray_union_elem);</div><div>+PG_FUNCTION_INFO_V1(anyarray_difference);</div><div>+PG_FUNCTION_INFO_V1(anyarray_difference_elem);</div><div>+</div><div>+/*</div><div>+ * deconstruct_two</div><div>+ *        Like deconstruct_arr_meta() but for two array inputs that must share</div><div>+ *        an element type.  The second array is allowed to be a different</div><div>+ *        ARRAY OID (it might come from another column) as long as the element</div><div>+ *        types match.</div><div>+ */</div><div>+static AnyArrayTypeInfo *</div><div>+deconstruct_two(FunctionCallInfo fcinfo,</div><div>+                ArrayType *a, ArrayType *b,</div><div>+                Datum **avals, int *anelems,</div><div>+                Datum **bvals, int *bnelems)</div><div>+{<!-- --></div><div>+    AnyArrayTypeInfo *meta;</div><div>+    bool       *nulls;</div><div>+</div><div>+    ANYARRAY_CHECK_ARRAY(a);</div><div>+    ANYARRAY_CHECK_ARRAY(b);</div><div>+</div><div>+    if (ARR_ELEMTYPE(a) != ARR_ELEMTYPE(b))</div><div>+        ereport(ERROR,</div><div>+                (errcode(ERRCODE_DATATYPE_MISMATCH),</div><div>+                 errmsg("cannot operate on arrays of different element types"),</div><div>+                 errdetail("Left operand has element type %s, right operand has %s.",</div><div>+                           format_type_be(ARR_ELEMTYPE(a)),</div><div>+                           format_type_be(ARR_ELEMTYPE(b)))));</div><div>+</div><div>+    meta = anyarray_get_meta(fcinfo, ARR_ELEMTYPE(a), false);</div><div>+</div><div>+    if (ARR_NDIM(a) == 0)</div><div>+    {<!-- --></div><div>+        *avals = NULL;</div><div>+        *anelems = 0;</div><div>+    }</div><div>+    else</div><div>+    {<!-- --></div><div>+        deconstruct_array(a, meta-&gt;element_type, meta-&gt;typlen,</div><div>+                          meta-&gt;typbyval, meta-&gt;typalign,</div><div>+                          avals, &amp;nulls, anelems);</div><div>+        pfree(nulls);</div><div>+    }</div><div>+</div><div>+    if (ARR_NDIM(b) == 0)</div><div>+    {<!-- --></div><div>+        *bvals = NULL;</div><div>+        *bnelems = 0;</div><div>+    }</div><div>+    else</div><div>+    {<!-- --></div><div>+        deconstruct_array(b, meta-&gt;element_type, meta-&gt;typlen,</div><div>+                          meta-&gt;typbyval, meta-&gt;typalign,</div><div>+                          bvals, &amp;nulls, bnelems);</div><div>+        pfree(nulls);</div><div>+    }</div><div>+</div><div>+    return meta;</div><div>+}</div><div>+</div><div>+/*</div><div>+ * Sort + de-dup in place.  Returns the new length.</div><div>+ */</div><div>+static int</div><div>+sort_uniq(Datum *values, int nelems, AnyArrayTypeInfo *meta)</div><div>+{<!-- --></div><div>+    if (nelems &lt;= 1)</div><div>+        return nelems;</div><div>+</div><div>+    qsort_arg(values, nelems, sizeof(Datum), anyarray_cmp_datum, meta);</div><div>+    return qunique_arg(values, nelems, sizeof(Datum),</div><div>+                       anyarray_cmp_datum, meta);</div><div>+}</div><div>+</div><div>+/*</div><div>+ * Intersection: returns the sorted, deduplicated values present in both</div><div>+ * inputs.</div><div>+ */</div><div>+Datum</div><div>+anyarray_intersect(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    ArrayType  *a = PG_GETARG_ARRAYTYPE_P(0);</div><div>+    ArrayType  *b = PG_GETARG_ARRAYTYPE_P(1);</div><div>+    AnyArrayTypeInfo *meta;</div><div>+    Datum       *av,</div><div>+               *bv,</div><div>+               *out;</div><div>+    int            an,</div><div>+                bn,</div><div>+                i = 0,</div><div>+                j = 0,</div><div>+                k = 0;</div><div>+</div><div>+    meta = deconstruct_two(fcinfo, a, b, &amp;av, &amp;an, &amp;bv, &amp;bn);</div><div>+</div><div>+    an = sort_uniq(av, an, meta);</div><div>+    bn = sort_uniq(bv, bn, meta);</div><div>+</div><div>+    out = (Datum *) palloc(sizeof(Datum) * Min(an, bn));</div><div>+    while (i &lt; an &amp;&amp; j &lt; bn)</div><div>+    {<!-- --></div><div>+        int            cmp = anyarray_cmp_datum(&amp;av[i], &amp;bv[j], meta);</div><div>+</div><div>+        if (cmp == 0)</div><div>+        {<!-- --></div><div>+            out[k++] = av[i];</div><div>+            i++;</div><div>+            j++;</div><div>+        }</div><div>+        else if (cmp &lt; 0)</div><div>+            i++;</div><div>+        else</div><div>+            j++;</div><div>+    }</div><div>+</div><div>+    PG_RETURN_ARRAYTYPE_P(make_array_from_datums(out, k, meta));</div><div>+}</div><div>+</div><div>+/*</div><div>+ * Union: returns the sorted, deduplicated values present in either input.</div><div>+ */</div><div>+Datum</div><div>+anyarray_union(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    ArrayType  *a = PG_GETARG_ARRAYTYPE_P(0);</div><div>+    ArrayType  *b = PG_GETARG_ARRAYTYPE_P(1);</div><div>+    AnyArrayTypeInfo *meta;</div><div>+    Datum       *av,</div><div>+               *bv,</div><div>+               *out;</div><div>+    int            an,</div><div>+                bn,</div><div>+                i = 0,</div><div>+                j = 0,</div><div>+                k = 0;</div><div>+</div><div>+    meta = deconstruct_two(fcinfo, a, b, &amp;av, &amp;an, &amp;bv, &amp;bn);</div><div>+</div><div>+    an = sort_uniq(av, an, meta);</div><div>+    bn = sort_uniq(bv, bn, meta);</div><div>+</div><div>+    out = (Datum *) palloc(sizeof(Datum) * (an + bn));</div><div>+    while (i &lt; an &amp;&amp; j &lt; bn)</div><div>+    {<!-- --></div><div>+        int            cmp = anyarray_cmp_datum(&amp;av[i], &amp;bv[j], meta);</div><div>+</div><div>+        if (cmp == 0)</div><div>+        {<!-- --></div><div>+            out[k++] = av[i];</div><div>+            i++;</div><div>+            j++;</div><div>+        }</div><div>+        else if (cmp &lt; 0)</div><div>+            out[k++] = av[i++];</div><div>+        else</div><div>+            out[k++] = bv[j++];</div><div>+    }</div><div>+    while (i &lt; an)</div><div>+        out[k++] = av[i++];</div><div>+    while (j &lt; bn)</div><div>+        out[k++] = bv[j++];</div><div>+</div><div>+    PG_RETURN_ARRAYTYPE_P(make_array_from_datums(out, k, meta));</div><div>+}</div><div>+</div><div>+/*</div><div>+ * array | element : add element if not already present, returning the</div><div>+ * sorted, deduplicated result.</div><div>+ */</div><div>+Datum</div><div>+anyarray_union_elem(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    ArrayType  *a = PG_GETARG_ARRAYTYPE_P(0);</div><div>+    Datum        elem = PG_GETARG_DATUM(1);</div><div>+    Oid            elem_type = get_fn_expr_argtype(fcinfo-&gt;flinfo, 1);</div><div>+    AnyArrayTypeInfo *meta;</div><div>+    Datum       *values;</div><div>+    int            nelems;</div><div>+    int            out_n;</div><div>+</div><div>+    ANYARRAY_CHECK_ARRAY(a);</div><div>+</div><div>+    if (ARR_ELEMTYPE(a) != elem_type)</div><div>+        ereport(ERROR,</div><div>+                (errcode(ERRCODE_DATATYPE_MISMATCH),</div><div>+                 errmsg("element type does not match array element type")));</div><div>+</div><div>+    meta = anyarray_get_meta(fcinfo, ARR_ELEMTYPE(a), false);</div><div>+</div><div>+    if (ARR_NDIM(a) == 0)</div><div>+    {<!-- --></div><div>+        nelems = 0;</div><div>+        values = (Datum *) palloc(sizeof(Datum));</div><div>+    }</div><div>+    else</div><div>+    {<!-- --></div><div>+        bool       *nulls;</div><div>+</div><div>+        deconstruct_array(a, meta-&gt;element_type, meta-&gt;typlen,</div><div>+                          meta-&gt;typbyval, meta-&gt;typalign,</div><div>+                          &amp;values, &amp;nulls, &amp;nelems);</div><div>+        pfree(nulls);</div><div>+        values = repalloc(values, sizeof(Datum) * (nelems + 1));</div><div>+    }</div><div>+</div><div>+    values[nelems++] = elem;</div><div>+</div><div>+    out_n = sort_uniq(values, nelems, meta);</div><div>+    PG_RETURN_ARRAYTYPE_P(make_array_from_datums(values, out_n, meta));</div><div>+}</div><div>+</div><div>+/*</div><div>+ * Difference: returns sorted, deduplicated values from "a" that are not in</div><div>+ * "b".</div><div>+ */</div><div>+Datum</div><div>+anyarray_difference(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    ArrayType  *a = PG_GETARG_ARRAYTYPE_P(0);</div><div>+    ArrayType  *b = PG_GETARG_ARRAYTYPE_P(1);</div><div>+    AnyArrayTypeInfo *meta;</div><div>+    Datum       *av,</div><div>+               *bv,</div><div>+               *out;</div><div>+    int            an,</div><div>+                bn,</div><div>+                i = 0,</div><div>+                j = 0,</div><div>+                k = 0;</div><div>+</div><div>+    meta = deconstruct_two(fcinfo, a, b, &amp;av, &amp;an, &amp;bv, &amp;bn);</div><div>+</div><div>+    an = sort_uniq(av, an, meta);</div><div>+    bn = sort_uniq(bv, bn, meta);</div><div>+</div><div>+    out = (Datum *) palloc(sizeof(Datum) * an);</div><div>+    while (i &lt; an &amp;&amp; j &lt; bn)</div><div>+    {<!-- --></div><div>+        int            cmp = anyarray_cmp_datum(&amp;av[i], &amp;bv[j], meta);</div><div>+</div><div>+        if (cmp == 0)</div><div>+        {<!-- --></div><div>+            i++;</div><div>+            j++;</div><div>+        }</div><div>+        else if (cmp &lt; 0)</div><div>+            out[k++] = av[i++];</div><div>+        else</div><div>+            j++;</div><div>+    }</div><div>+    while (i &lt; an)</div><div>+        out[k++] = av[i++];</div><div>+</div><div>+    PG_RETURN_ARRAYTYPE_P(make_array_from_datums(out, k, meta));</div><div>+}</div><div>+</div><div>+/*</div><div>+ * array - element : remove all occurrences of "elem", preserving order.</div><div>+ * (Note: intarray returns the input order-preserved; we do the same.)</div><div>+ */</div><div>+Datum</div><div>+anyarray_difference_elem(PG_FUNCTION_ARGS)</div><div>+{<!-- --></div><div>+    ArrayType  *a = PG_GETARG_ARRAYTYPE_P(0);</div><div>+    Datum        elem = PG_GETARG_DATUM(1);</div><div>+    Oid            elem_type = get_fn_expr_argtype(fcinfo-&gt;flinfo, 1);</div><div>+    AnyArrayTypeInfo *meta;</div><div>+    Datum       *values;</div><div>+    int            nelems;</div><div>+    int            i,</div><div>+                k = 0;</div><div>+</div><div>+    ANYARRAY_CHECK_ARRAY(a);</div><div>+</div><div>+    if (ARR_ELEMTYPE(a) != elem_type)</div><div>+        ereport(ERROR,</div><div>+                (errcode(ERRCODE_DATATYPE_MISMATCH),</div><div>+                 errmsg("element type does not match array element type")));</div><div>+</div><div>+    meta = anyarray_get_meta(fcinfo, ARR_ELEMTYPE(a), false);</div><div>+</div><div>+    if (ARR_NDIM(a) == 0)</div><div>+        PG_RETURN_ARRAYTYPE_P(construct_empty_array(meta-&gt;element_type));</div><div>+</div><div>+    {<!-- --></div><div>+        bool       *nulls;</div><div>+</div><div>+        deconstruct_array(a, meta-&gt;element_type, meta-&gt;typlen,</div><div>+                          meta-&gt;typbyval, meta-&gt;typalign,</div><div>+                          &amp;values, &amp;nulls, &amp;nelems);</div><div>+        pfree(nulls);</div><div>+    }</div><div>+</div><div>+    for (i = 0; i &lt; nelems; i++)</div><div>+    {<!-- --></div><div>+        Datum        eq = FunctionCall2Coll(&amp;meta-&gt;eq_proc, meta-&gt;typcollation,</div><div>+                                           values[i], elem);</div><div>+</div><div>+        if (!DatumGetBool(eq))</div><div>+            values[k++] = values[i];</div><div>+    }</div><div>+</div><div>+    PG_RETURN_ARRAYTYPE_P(make_array_from_datums(values, k, meta));</div><div>+}</div><div>diff --git a/contrib/anyarray/expected/anyarray.out b/contrib/anyarray/expected/anyarray.out</div><div>new file mode 100644</div><div>index 00000000000..b17c6ef033e</div><div>--- /dev/null</div><div>+++ b/contrib/anyarray/expected/anyarray.out</div><div>@@ -0,0 +1,727 @@</div><div>+CREATE EXTENSION anyarray;</div><div>+--</div><div>+-- Phase 1: set operations, helpers and operators for int8, uuid, text</div><div>+--</div><div>+-- ===== int8 =====</div><div>+SELECT anyarray_sort(ARRAY[3, 1, 2, 1]::int8[]);</div><div>+ anyarray_sort </div><div>+---------------</div><div>+ {1,1,2,3}</div><div>+(1 row)</div><div>+</div><div>+SELECT anyarray_sort(ARRAY[3, 1, 2, 1]::int8[], 'desc');</div><div>+ anyarray_sort </div><div>+---------------</div><div>+ {3,2,1,1}</div><div>+(1 row)</div><div>+</div><div>+SELECT anyarray_sort(ARRAY[]::int8[]);</div><div>+ anyarray_sort </div><div>+---------------</div><div>+ {}</div><div>+(1 row)</div><div>+</div><div>+SELECT anyarray_uniq(ARRAY[1, 1, 2, 3, 3, 2]::int8[]);</div><div>+ anyarray_uniq </div><div>+---------------</div><div>+ {1,2,3}</div><div>+(1 row)</div><div>+</div><div>+SELECT anyarray_idx(ARRAY[10, 20, 30]::int8[], 20::int8);</div><div>+ anyarray_idx </div><div>+--------------</div><div>+            2</div><div>+(1 row)</div><div>+</div><div>+SELECT anyarray_idx(ARRAY[10, 20, 30]::int8[], 99::int8);</div><div>+ anyarray_idx </div><div>+--------------</div><div>+            0</div><div>+(1 row)</div><div>+</div><div>+SELECT anyarray_subarray(ARRAY[1,2,3,4,5]::int8[], 2, 2);</div><div>+ anyarray_subarray </div><div>+-------------------</div><div>+ {2,3}</div><div>+(1 row)</div><div>+</div><div>+SELECT anyarray_subarray(ARRAY[1,2,3,4,5]::int8[], 3);</div><div>+ anyarray_subarray </div><div>+-------------------</div><div>+ {3,4,5}</div><div>+(1 row)</div><div>+</div><div>+SELECT anyarray_subarray(ARRAY[1,2,3]::int8[], 5, 1);</div><div>+ anyarray_subarray </div><div>+-------------------</div><div>+ {}</div><div>+(1 row)</div><div>+</div><div>+SELECT ARRAY[1,2,3]::int8[] &amp; ARRAY[2,3,4]::int8[];</div><div>+ ?column? </div><div>+----------</div><div>+ {2,3}</div><div>+(1 row)</div><div>+</div><div>+SELECT ARRAY[1,2,3]::int8[] | ARRAY[3,4,5]::int8[];</div><div>+  ?column?   </div><div>+-------------</div><div>+ {1,2,3,4,5}</div><div>+(1 row)</div><div>+</div><div>+SELECT ARRAY[1,2,3]::int8[] | 4::int8;</div><div>+ ?column?  </div><div>+-----------</div><div>+ {1,2,3,4}</div><div>+(1 row)</div><div>+</div><div>+SELECT ARRAY[1,2,3,4]::int8[] - ARRAY[2,4]::int8[];</div><div>+ ?column? </div><div>+----------</div><div>+ {1,3}</div><div>+(1 row)</div><div>+</div><div>+SELECT ARRAY[1,2,2,3,2]::int8[] - 2::int8;</div><div>+ ?column? </div><div>+----------</div><div>+ {1,3}</div><div>+(1 row)</div><div>+</div><div>+SELECT # ARRAY[10,20,30]::int8[];</div><div>+ ?column? </div><div>+----------</div><div>+        3</div><div>+(1 row)</div><div>+</div><div>+SELECT ARRAY[10,20,30]::int8[] # 20::int8;</div><div>+ ?column? </div><div>+----------</div><div>+        2</div><div>+(1 row)</div><div>+</div><div>+-- ===== uuid =====</div><div>+SELECT anyarray_sort(ARRAY[</div><div>+  '00000000-0000-0000-0000-000000000003'::uuid,</div><div>+  '00000000-0000-0000-0000-000000000001',</div><div>+  '00000000-0000-0000-0000-000000000002']);</div><div>+                                                  anyarray_sort                                                   </div><div>+------------------------------------------------------------------------------------------------------------------</div><div>+ {00000000-0000-0000-0000-000000000001,00000000-0000-0000-0000-000000000002,00000000-0000-0000-0000-000000000003}</div><div>+(1 row)</div><div>+</div><div>+SELECT anyarray_uniq(ARRAY[</div><div>+  '00000000-0000-0000-0000-000000000001'::uuid,</div><div>+  '00000000-0000-0000-0000-000000000001',</div><div>+  '00000000-0000-0000-0000-000000000002']);</div><div>+                                anyarray_uniq                                </div><div>+-----------------------------------------------------------------------------</div><div>+ {00000000-0000-0000-0000-000000000001,00000000-0000-0000-0000-000000000002}</div><div>+(1 row)</div><div>+</div><div>+SELECT anyarray_idx(ARRAY[</div><div>+  '00000000-0000-0000-0000-000000000001'::uuid,</div><div>+  '00000000-0000-0000-0000-000000000002'],</div><div>+  '00000000-0000-0000-0000-000000000002'::uuid);</div><div>+ anyarray_idx </div><div>+--------------</div><div>+            2</div><div>+(1 row)</div><div>+</div><div>+SELECT ARRAY['00000000-0000-0000-0000-000000000001'::uuid,</div><div>+             '00000000-0000-0000-0000-000000000002']</div><div>+     &amp; ARRAY['00000000-0000-0000-0000-000000000002'::uuid,</div><div>+             '00000000-0000-0000-0000-000000000003'];</div><div>+                ?column?                </div><div>+----------------------------------------</div><div>+ {00000000-0000-0000-0000-000000000002}</div><div>+(1 row)</div><div>+</div><div>+SELECT ARRAY['00000000-0000-0000-0000-000000000001'::uuid]</div><div>+     | '00000000-0000-0000-0000-000000000002'::uuid;</div><div>+                                  ?column?                                   </div><div>+-----------------------------------------------------------------------------</div><div>+ {00000000-0000-0000-0000-000000000001,00000000-0000-0000-0000-000000000002}</div><div>+(1 row)</div><div>+</div><div>+-- ===== text =====</div><div>+SELECT anyarray_sort(ARRAY['banana','apple','cherry']);</div><div>+     anyarray_sort     </div><div>+-----------------------</div><div>+ {apple,banana,cherry}</div><div>+(1 row)</div><div>+</div><div>+SELECT anyarray_sort(ARRAY['banana','apple','cherry'], 'desc');</div><div>+     anyarray_sort     </div><div>+-----------------------</div><div>+ {cherry,banana,apple}</div><div>+(1 row)</div><div>+</div><div>+SELECT anyarray_uniq(ARRAY['a','b','a','c','b']);</div><div>+ anyarray_uniq </div><div>+---------------</div><div>+ {a,b,c}</div><div>+(1 row)</div><div>+</div><div>+SELECT anyarray_idx(ARRAY['a','b','c'], 'b'::text);</div><div>+ anyarray_idx </div><div>+--------------</div><div>+            2</div><div>+(1 row)</div><div>+</div><div>+SELECT ARRAY['a','b','c']::text[] &amp; ARRAY['b','c','d']::text[];</div><div>+ ?column? </div><div>+----------</div><div>+ {b,c}</div><div>+(1 row)</div><div>+</div><div>+SELECT ARRAY['a','b','c']::text[] | 'd'::text;</div><div>+ ?column?  </div><div>+-----------</div><div>+ {a,b,c,d}</div><div>+(1 row)</div><div>+</div><div>+SELECT ARRAY['a','b','c','b']::text[] - 'b'::text;</div><div>+ ?column? </div><div>+----------</div><div>+ {a,c}</div><div>+(1 row)</div><div>+</div><div>+-- ===== error cases =====</div><div>+-- multi-dim</div><div>+SELECT anyarray_sort(ARRAY[[1,2],[3,4]]::int8[]);</div><div>+ERROR:  multidimensional arrays are not supported</div><div>+-- nulls</div><div>+SELECT anyarray_sort(ARRAY[1, NULL, 2]::int8[]);</div><div>+ERROR:  array must not contain nulls</div><div>+-- bad direction</div><div>+SELECT anyarray_sort(ARRAY[1,2,3]::int8[], 'bogus');</div><div>+ERROR:  second parameter must be "asc" or "desc"</div><div>+--</div><div>+-- Phase 2: anyquery and @@ operator</div><div>+--</div><div>+-- parsing + output round-trip</div><div>+SELECT '1 &amp; 2'::anyquery::text;</div><div>+ text  </div><div>+-------</div><div>+ 1 &amp; 2</div><div>+(1 row)</div><div>+</div><div>+SELECT '1 &amp; 2 | 3'::anyquery::text;</div><div>+   text    </div><div>+-----------</div><div>+ 1 &amp; 2 | 3</div><div>+(1 row)</div><div>+</div><div>+SELECT '(1 | 2) &amp; 3'::anyquery::text;</div><div>+     text      </div><div>+---------------</div><div>+ ( 1 | 2 ) &amp; 3</div><div>+(1 row)</div><div>+</div><div>+SELECT '!1 &amp; 2'::anyquery::text;</div><div>+  text  </div><div>+--------</div><div>+ !1 &amp; 2</div><div>+(1 row)</div><div>+</div><div>+SELECT '!(1 | 2) &amp; 3'::anyquery::text;</div><div>+        text        </div><div>+--------------------</div><div>+ !( ( 1 | 2 ) ) &amp; 3</div><div>+(1 row)</div><div>+</div><div>+SELECT '"hello world" | foo'::anyquery::text;</div><div>+        text         </div><div>+---------------------</div><div>+ "hello world" | foo</div><div>+(1 row)</div><div>+</div><div>+SELECT anyquery_querytree('1 &amp; 2 | 3'::anyquery);</div><div>+ anyquery_querytree </div><div>+--------------------</div><div>+ 1 2 &amp; 3 |</div><div>+(1 row)</div><div>+</div><div>+-- int8 matching</div><div>+SELECT ARRAY[1,2,3]::int8[] @@ '1'::anyquery;</div><div>+ ?column? </div><div>+----------</div><div>+ t</div><div>+(1 row)</div><div>+</div><div>+SELECT ARRAY[1,2,3]::int8[] @@ '1 &amp; 2'::anyquery;</div><div>+ ?column? </div><div>+----------</div><div>+ t</div><div>+(1 row)</div><div>+</div><div>+SELECT ARRAY[1,2,3]::int8[] @@ '1 &amp; 4'::anyquery;</div><div>+ ?column? </div><div>+----------</div><div>+ f</div><div>+(1 row)</div><div>+</div><div>+SELECT ARRAY[1,2,3]::int8[] @@ '1 | 4'::anyquery;</div><div>+ ?column? </div><div>+----------</div><div>+ t</div><div>+(1 row)</div><div>+</div><div>+SELECT ARRAY[1,2,3]::int8[] @@ '!4'::anyquery;</div><div>+ ?column? </div><div>+----------</div><div>+ t</div><div>+(1 row)</div><div>+</div><div>+SELECT ARRAY[1,2,3]::int8[] @@ '!1'::anyquery;</div><div>+ ?column? </div><div>+----------</div><div>+ f</div><div>+(1 row)</div><div>+</div><div>+SELECT ARRAY[1,2,3]::int8[] @@ '!4 &amp; 1'::anyquery;</div><div>+ ?column? </div><div>+----------</div><div>+ t</div><div>+(1 row)</div><div>+</div><div>+SELECT ARRAY[1,2,3]::int8[] @@ '(1 | 4) &amp; (2 | 5)'::anyquery;</div><div>+ ?column? </div><div>+----------</div><div>+ t</div><div>+(1 row)</div><div>+</div><div>+-- commutator</div><div>+SELECT '1 &amp; 2'::anyquery ~~ ARRAY[1,2,3]::int8[];</div><div>+ ?column? </div><div>+----------</div><div>+ t</div><div>+(1 row)</div><div>+</div><div>+SELECT '1 &amp; 4'::anyquery ~~ ARRAY[1,2,3]::int8[];</div><div>+ ?column? </div><div>+----------</div><div>+ f</div><div>+(1 row)</div><div>+</div><div>+-- uuid</div><div>+SELECT ARRAY['00000000-0000-0000-0000-000000000001'::uuid,</div><div>+             '00000000-0000-0000-0000-000000000002']</div><div>+       @@ '00000000-0000-0000-0000-000000000001 &amp; 00000000-0000-0000-0000-000000000002'::anyquery;</div><div>+ ?column? </div><div>+----------</div><div>+ t</div><div>+(1 row)</div><div>+</div><div>+SELECT ARRAY['00000000-0000-0000-0000-000000000001'::uuid]</div><div>+       @@ '00000000-0000-0000-0000-000000000002'::anyquery;</div><div>+ ?column? </div><div>+----------</div><div>+ f</div><div>+(1 row)</div><div>+</div><div>+-- text</div><div>+SELECT ARRAY['apple','banana','cherry']::text[] @@ 'apple &amp; banana'::anyquery;</div><div>+ ?column? </div><div>+----------</div><div>+ t</div><div>+(1 row)</div><div>+</div><div>+SELECT ARRAY['apple','banana','cherry']::text[] @@ '"banana" | grape'::anyquery;</div><div>+ ?column? </div><div>+----------</div><div>+ t</div><div>+(1 row)</div><div>+</div><div>+SELECT ARRAY['apple','banana','cherry']::text[] @@ 'durian | grape'::anyquery;</div><div>+ ?column? </div><div>+----------</div><div>+ f</div><div>+(1 row)</div><div>+</div><div>+-- empty array</div><div>+SELECT ARRAY[]::int8[] @@ '1'::anyquery;</div><div>+ ?column? </div><div>+----------</div><div>+ f</div><div>+(1 row)</div><div>+</div><div>+SELECT ARRAY[]::int8[] @@ '!1'::anyquery;</div><div>+ ?column? </div><div>+----------</div><div>+ t</div><div>+(1 row)</div><div>+</div><div>+-- parse errors</div><div>+SELECT ''::anyquery;</div><div>+ERROR:  unexpected end of input in anyquery</div><div>+LINE 1: SELECT ''::anyquery;</div><div>+               ^</div><div>+SELECT '1 &amp;'::anyquery;</div><div>+ERROR:  unexpected end of input in anyquery</div><div>+LINE 1: SELECT '1 &amp;'::anyquery;</div><div>+               ^</div><div>+SELECT '1 &amp; (2'::anyquery;</div><div>+ERROR:  missing closing parenthesis in anyquery</div><div>+LINE 1: SELECT '1 &amp; (2'::anyquery;</div><div>+               ^</div><div>+SELECT '1 ) 2'::anyquery;</div><div>+ERROR:  unexpected trailing input in anyquery</div><div>+LINE 1: SELECT '1 ) 2'::anyquery;</div><div>+               ^</div><div>+-- runtime errors: token cannot be parsed as element type</div><div>+SELECT ARRAY[1,2]::int8[] @@ 'abc'::anyquery;</div><div>+ERROR:  invalid input syntax for type bigint: "abc"</div><div>+--</div><div>+-- Phase 3: GiST signature index</div><div>+--</div><div>+-- amvalidate: well-formed opclass</div><div>+SELECT amname, opcname FROM pg_opclass opc</div><div>+LEFT JOIN pg_am am ON am.oid = opcmethod</div><div>+WHERE opc.opcname = 'anyarray_gist_ops' AND NOT amvalidate(opc.oid);</div><div>+ amname | opcname </div><div>+--------+---------</div><div>+(0 rows)</div><div>+</div><div>+-- int8 GiST: build deterministic table</div><div>+CREATE TABLE anyarray_gist_int8 (id int, a int8[]);</div><div>+INSERT INTO anyarray_gist_int8 VALUES</div><div>+  (1, ARRAY[1,2,3]::int8[]),</div><div>+  (2, ARRAY[10,20,30]::int8[]),</div><div>+  (3, ARRAY[10,20,30]::int8[]),</div><div>+  (4, ARRAY[1,2,3,4,5]::int8[]),</div><div>+  (5, ARRAY[100,200]::int8[]);</div><div>+CREATE INDEX anyarray_gist_int8_idx</div><div>+  ON anyarray_gist_int8 USING gist(a anyarray_gist_ops);</div><div>+SET enable_seqscan = off;</div><div>+SELECT id FROM anyarray_gist_int8 WHERE a @&gt; ARRAY[1,2]::int8[] ORDER BY id;</div><div>+ id </div><div>+----</div><div>+  1</div><div>+  4</div><div>+(2 rows)</div><div>+</div><div>+SELECT id FROM anyarray_gist_int8 WHERE a &amp;&amp; ARRAY[10,200]::int8[] ORDER BY id;</div><div>+ id </div><div>+----</div><div>+  2</div><div>+  3</div><div>+  5</div><div>+(3 rows)</div><div>+</div><div>+SELECT id FROM anyarray_gist_int8 WHERE a = ARRAY[10,20,30]::int8[] ORDER BY id;</div><div>+ id </div><div>+----</div><div>+  2</div><div>+  3</div><div>+(2 rows)</div><div>+</div><div>+SELECT id FROM anyarray_gist_int8 WHERE a &lt;@ ARRAY[1,2,3,4,5]::int8[] ORDER BY id;</div><div>+ id </div><div>+----</div><div>+  1</div><div>+  4</div><div>+(2 rows)</div><div>+</div><div>+SELECT id FROM anyarray_gist_int8 WHERE a @@ '10 &amp; 20'::anyquery ORDER BY id;</div><div>+ id </div><div>+----</div><div>+  2</div><div>+  3</div><div>+(2 rows)</div><div>+</div><div>+SELECT id FROM anyarray_gist_int8 WHERE a @@ '1 | 100'::anyquery ORDER BY id;</div><div>+ id </div><div>+----</div><div>+  1</div><div>+  4</div><div>+  5</div><div>+(3 rows)</div><div>+</div><div>+SELECT id FROM anyarray_gist_int8 WHERE a @@ '!1 &amp; 10'::anyquery ORDER BY id;</div><div>+ id </div><div>+----</div><div>+  2</div><div>+  3</div><div>+(2 rows)</div><div>+</div><div>+-- result consistency: GiST must agree with seqscan</div><div>+SELECT (</div><div>+  SELECT count(*) FROM anyarray_gist_int8 WHERE a @&gt; ARRAY[10]::int8[]</div><div>+) = (</div><div>+  SELECT count(*) FROM (SELECT 1 FROM anyarray_gist_int8 WHERE a @&gt; ARRAY[10]::int8[]) s</div><div>+) AS gist_matches_seqscan;</div><div>+ gist_matches_seqscan </div><div>+----------------------</div><div>+ t</div><div>+(1 row)</div><div>+</div><div>+RESET enable_seqscan;</div><div>+-- text GiST</div><div>+CREATE TABLE anyarray_gist_text (id int, a text[]);</div><div>+INSERT INTO anyarray_gist_text VALUES</div><div>+  (1, ARRAY['apple','banana']),</div><div>+  (2, ARRAY['banana','cherry']),</div><div>+  (3, ARRAY['apple','cherry','durian']);</div><div>+CREATE INDEX anyarray_gist_text_idx</div><div>+  ON anyarray_gist_text USING gist(a anyarray_gist_ops(siglen=64));</div><div>+SET enable_seqscan = off;</div><div>+SELECT id FROM anyarray_gist_text WHERE a @&gt; ARRAY['apple']::text[] ORDER BY id;</div><div>+ id </div><div>+----</div><div>+  1</div><div>+  3</div><div>+(2 rows)</div><div>+</div><div>+SELECT id FROM anyarray_gist_text WHERE a @@ 'apple &amp; cherry'::anyquery ORDER BY id;</div><div>+ id </div><div>+----</div><div>+  3</div><div>+(1 row)</div><div>+</div><div>+RESET enable_seqscan;</div><div>+-- siglen bounds</div><div>+CREATE INDEX ON anyarray_gist_text USING gist(a anyarray_gist_ops(siglen=0));</div><div>+ERROR:  value 0 out of bounds for option "siglen"</div><div>+DETAIL:  Valid values are between "1" and "2024".</div><div>+CREATE INDEX ON anyarray_gist_text USING gist(a anyarray_gist_ops(siglen=8193));</div><div>+ERROR:  value 8193 out of bounds for option "siglen"</div><div>+DETAIL:  Valid values are between "1" and "2024".</div><div>+--</div><div>+-- Phase 4: GIN index (per-type, supports standard ops + @@)</div><div>+--</div><div>+-- amvalidate: all three opclasses</div><div>+SELECT amname, opcname FROM pg_opclass opc</div><div>+LEFT JOIN pg_am am ON am.oid = opcmethod</div><div>+WHERE opc.opcname LIKE '%anyquery_gin_ops' AND NOT amvalidate(opc.oid);</div><div>+ amname | opcname </div><div>+--------+---------</div><div>+(0 rows)</div><div>+</div><div>+-- int8 GIN</div><div>+CREATE TABLE anyarray_gin_int8 (id int, a int8[]);</div><div>+INSERT INTO anyarray_gin_int8 VALUES</div><div>+  (1, ARRAY[1,2,3]::int8[]),</div><div>+  (2, ARRAY[10,20,30]::int8[]),</div><div>+  (3, ARRAY[10,20,30]::int8[]),</div><div>+  (4, ARRAY[1,2,3,4,5]::int8[]),</div><div>+  (5, ARRAY[100,200]::int8[]);</div><div>+CREATE INDEX anyarray_gin_int8_idx</div><div>+  ON anyarray_gin_int8 USING gin(a int8_anyquery_gin_ops);</div><div>+SET enable_seqscan = off;</div><div>+SELECT id FROM anyarray_gin_int8 WHERE a @&gt; ARRAY[1,2]::int8[] ORDER BY id;</div><div>+ id </div><div>+----</div><div>+  1</div><div>+  4</div><div>+(2 rows)</div><div>+</div><div>+SELECT id FROM anyarray_gin_int8 WHERE a &amp;&amp; ARRAY[10,200]::int8[] ORDER BY id;</div><div>+ id </div><div>+----</div><div>+  2</div><div>+  3</div><div>+  5</div><div>+(3 rows)</div><div>+</div><div>+SELECT id FROM anyarray_gin_int8 WHERE a @@ '10 &amp; 20'::anyquery ORDER BY id;</div><div>+ id </div><div>+----</div><div>+  2</div><div>+  3</div><div>+(2 rows)</div><div>+</div><div>+SELECT id FROM anyarray_gin_int8 WHERE a @@ '(1 &amp; 2) | 100'::anyquery ORDER BY id;</div><div>+ id </div><div>+----</div><div>+  1</div><div>+  4</div><div>+  5</div><div>+(3 rows)</div><div>+</div><div>+SELECT id FROM anyarray_gin_int8 WHERE a @@ '!1'::anyquery ORDER BY id;</div><div>+ id </div><div>+----</div><div>+  2</div><div>+  3</div><div>+  5</div><div>+(3 rows)</div><div>+</div><div>+-- uuid GIN</div><div>+CREATE TABLE anyarray_gin_uuid (id int, a uuid[]);</div><div>+INSERT INTO anyarray_gin_uuid VALUES</div><div>+  (1, ARRAY['11111111-1111-1111-1111-111111111111'::uuid,</div><div>+            '22222222-2222-2222-2222-222222222222']),</div><div>+  (2, ARRAY['33333333-3333-3333-3333-333333333333'::uuid]),</div><div>+  (3, ARRAY['11111111-1111-1111-1111-111111111111'::uuid,</div><div>+            '33333333-3333-3333-3333-333333333333']);</div><div>+CREATE INDEX anyarray_gin_uuid_idx</div><div>+  ON anyarray_gin_uuid USING gin(a uuid_anyquery_gin_ops);</div><div>+SET enable_seqscan = off;</div><div>+SELECT id FROM anyarray_gin_uuid</div><div>+  WHERE a @@ '11111111-1111-1111-1111-111111111111 &amp; 22222222-2222-2222-2222-222222222222'::anyquery</div><div>+  ORDER BY id;</div><div>+ id </div><div>+----</div><div>+  1</div><div>+(1 row)</div><div>+</div><div>+SELECT id FROM anyarray_gin_uuid</div><div>+  WHERE a @&gt; ARRAY['11111111-1111-1111-1111-111111111111'::uuid]</div><div>+  ORDER BY id;</div><div>+ id </div><div>+----</div><div>+  1</div><div>+  3</div><div>+(2 rows)</div><div>+</div><div>+RESET enable_seqscan;</div><div>+-- text GIN</div><div>+CREATE TABLE anyarray_gin_text (id int, a text[]);</div><div>+INSERT INTO anyarray_gin_text VALUES</div><div>+  (1, ARRAY['apple','banana']),</div><div>+  (2, ARRAY['banana','cherry']),</div><div>+  (3, ARRAY['apple','cherry','durian']);</div><div>+CREATE INDEX anyarray_gin_text_idx</div><div>+  ON anyarray_gin_text USING gin(a text_anyquery_gin_ops);</div><div>+SET enable_seqscan = off;</div><div>+SELECT id FROM anyarray_gin_text WHERE a @@ 'apple &amp; cherry'::anyquery ORDER BY id;</div><div>+ id </div><div>+----</div><div>+  3</div><div>+(1 row)</div><div>+</div><div>+SELECT id FROM anyarray_gin_text WHERE a @@ '"durian"'::anyquery ORDER BY id;</div><div>+ id </div><div>+----</div><div>+  3</div><div>+(1 row)</div><div>+</div><div>+SELECT id FROM anyarray_gin_text WHERE a @@ 'apple | grape'::anyquery ORDER BY id;</div><div>+ id </div><div>+----</div><div>+  1</div><div>+  3</div><div>+(2 rows)</div><div>+</div><div>+SELECT id FROM anyarray_gin_text WHERE a @@ '!banana'::anyquery ORDER BY id;</div><div>+ id </div><div>+----</div><div>+  3</div><div>+(1 row)</div><div>+</div><div>+RESET enable_seqscan;</div><div>+--</div><div>+-- Phase 5: cross-AM consistency and edge cases</div><div>+--</div><div>+-- Build a larger deterministic int8 table and index it with both GiST and</div><div>+-- GIN.  Then run each candidate query under seqscan, GiST and GIN and check</div><div>+-- that all three plans return the same row set.</div><div>+--</div><div>+CREATE TABLE anyarray_xcheck (id int, a int8[]);</div><div>+INSERT INTO anyarray_xcheck</div><div>+SELECT g,</div><div>+       ARRAY[(g % 7)::int8, ((g * 3) % 11)::int8, ((g + 1) % 5)::int8]</div><div>+FROM generate_series(1, 200) g;</div><div>+-- a few hand-picked rows to exercise common values</div><div>+INSERT INTO anyarray_xcheck VALUES</div><div>+  (1001, ARRAY[1,2,3,4,5]::int8[]),</div><div>+  (1002, ARRAY[1,2,3,4,5]::int8[]),</div><div>+  (1003, ARRAY[100,200,300]::int8[]),</div><div>+  (1004, ARRAY[]::int8[]),</div><div>+  (1005, NULL);</div><div>+CREATE INDEX anyarray_xcheck_gist ON anyarray_xcheck</div><div>+  USING gist(a anyarray_gist_ops);</div><div>+CREATE INDEX anyarray_xcheck_gin ON anyarray_xcheck</div><div>+  USING gin(a int8_anyquery_gin_ops);</div><div>+-- Run each predicate three times: pure seqscan, GiST-only, GIN-only.</div><div>+-- All three result sets must match.</div><div>+CREATE FUNCTION anyarray_xcheck_match(pred text)</div><div>+RETURNS TABLE(gist_ok bool, gin_ok bool)</div><div>+LANGUAGE plpgsql AS $$</div><div>+DECLARE</div><div>+  seq int[]; gst int[]; gin int[];</div><div>+BEGIN</div><div>+  SET LOCAL enable_seqscan = on;</div><div>+  SET LOCAL enable_indexscan = off;</div><div>+  SET LOCAL enable_bitmapscan = off;</div><div>+  EXECUTE 'SELECT array_agg(id ORDER BY id) FROM anyarray_xcheck WHERE '</div><div>+          || pred INTO seq;</div><div>+</div><div>+  -- Force GiST by hiding the GIN index.</div><div>+  ALTER INDEX anyarray_xcheck_gin SET (fastupdate = off);</div><div>+  SET LOCAL enable_seqscan = off;</div><div>+  SET LOCAL enable_indexscan = on;</div><div>+  SET LOCAL enable_bitmapscan = on;</div><div>+  DROP INDEX anyarray_xcheck_gin;</div><div>+  EXECUTE 'SELECT array_agg(id ORDER BY id) FROM anyarray_xcheck WHERE '</div><div>+          || pred INTO gst;</div><div>+  CREATE INDEX anyarray_xcheck_gin ON anyarray_xcheck</div><div>+    USING gin(a int8_anyquery_gin_ops);</div><div>+</div><div>+  -- Force GIN by hiding GiST.</div><div>+  DROP INDEX anyarray_xcheck_gist;</div><div>+  EXECUTE 'SELECT array_agg(id ORDER BY id) FROM anyarray_xcheck WHERE '</div><div>+          || pred INTO gin;</div><div>+  CREATE INDEX anyarray_xcheck_gist ON anyarray_xcheck</div><div>+    USING gist(a anyarray_gist_ops);</div><div>+</div><div>+  gist_ok := seq IS NOT DISTINCT FROM gst;</div><div>+  gin_ok  := seq IS NOT DISTINCT FROM gin;</div><div>+  RETURN NEXT;</div><div>+END $$;</div><div>+SELECT pred, gist_ok, gin_ok FROM (VALUES</div><div>+  ('a @&gt; ARRAY[1,2]::int8[]'),</div><div>+  ('a @&gt; ARRAY[100,200]::int8[]'),</div><div>+  ('a &amp;&amp; ARRAY[5,99]::int8[]'),</div><div>+  ('a = ARRAY[1,2,3,4,5]::int8[]'),</div><div>+  ('a @@ ''1 &amp; 2''::anyquery'),</div><div>+  ('a @@ ''100 | 999''::anyquery'),</div><div>+  ('a @@ ''!1 &amp; 2''::anyquery')</div><div>+) v(pred), LATERAL anyarray_xcheck_match(pred);</div><div>+             pred             | gist_ok | gin_ok </div><div>+------------------------------+---------+--------</div><div>+ a @&gt; ARRAY[1,2]::int8[]      | t       | t</div><div>+ a @&gt; ARRAY[100,200]::int8[]  | t       | t</div><div>+ a &amp;&amp; ARRAY[5,99]::int8[]     | t       | t</div><div>+ a = ARRAY[1,2,3,4,5]::int8[] | t       | t</div><div>+ a @@ '1 &amp; 2'::anyquery       | t       | t</div><div>+ a @@ '100 | 999'::anyquery   | t       | t</div><div>+ a @@ '!1 &amp; 2'::anyquery      | t       | t</div><div>+(7 rows)</div><div>+</div><div>+-- Edge cases: empty / NULL arrays via index</div><div>+SET enable_seqscan = off;</div><div>+SELECT id FROM anyarray_xcheck WHERE a @&gt; ARRAY[]::int8[] AND id = 1004;</div><div>+  id  </div><div>+------</div><div>+ 1004</div><div>+(1 row)</div><div>+</div><div>+SELECT id FROM anyarray_xcheck WHERE a &lt;@ ARRAY[1,2,3]::int8[] AND id &lt; 100 ORDER BY id LIMIT 3;</div><div>+ id </div><div>+----</div><div>+  1</div><div>+ 15</div><div>+ 30</div><div>+(3 rows)</div><div>+</div><div>+SELECT count(*) FROM anyarray_xcheck WHERE a IS NULL;</div><div>+ count </div><div>+-------</div><div>+     1</div><div>+(1 row)</div><div>+</div><div>+RESET enable_seqscan;</div><div>+-- DELETE / VACUUM / re-query through index</div><div>+DELETE FROM anyarray_xcheck WHERE id BETWEEN 1 AND 50;</div><div>+VACUUM anyarray_xcheck;</div><div>+SET enable_seqscan = off;</div><div>+SELECT count(*) FROM anyarray_xcheck WHERE a @@ '1 | 2'::anyquery;</div><div>+ count </div><div>+-------</div><div>+    98</div><div>+(1 row)</div><div>+</div><div>+RESET enable_seqscan;</div><div>+DROP FUNCTION anyarray_xcheck_match(text);</div><div>diff --git a/contrib/anyarray/meson.build b/contrib/anyarray/meson.build</div><div>new file mode 100644</div><div>index 00000000000..a20646b82b2</div><div>--- /dev/null</div><div>+++ b/contrib/anyarray/meson.build</div><div>@@ -0,0 +1,38 @@</div><div>+# Copyright (c) 2026, PostgreSQL Global Development Group</div><div>+</div><div>+anyarray_sources = files(</div><div>+  'anyarray.c',</div><div>+  'anyarray_bool.c',</div><div>+  'anyarray_gin.c',</div><div>+  'anyarray_gist.c',</div><div>+  'anyarray_op.c',</div><div>+)</div><div>+</div><div>+if host_system == 'windows'</div><div>+  anyarray_sources += rc_lib_gen.process(win32ver_rc, extra_args: [</div><div>+    '--NAME', 'anyarray',</div><div>+    '--FILEDESC', 'anyarray - operations and indexes for arrays of any type',])</div><div>+endif</div><div>+</div><div>+anyarray = shared_module('anyarray',</div><div>+  anyarray_sources,</div><div>+  kwargs: contrib_mod_args,</div><div>+)</div><div>+contrib_targets += anyarray</div><div>+</div><div>+install_data(</div><div>+  'anyarray--1.0.sql',</div><div>+  'anyarray.control',</div><div>+  kwargs: contrib_data_args,</div><div>+)</div><div>+</div><div>+tests += {<!-- --></div><div>+  'name': 'anyarray',</div><div>+  'sd': meson.current_source_dir(),</div><div>+  'bd': meson.current_build_dir(),</div><div>+  'regress': {<!-- --></div><div>+    'sql': [</div><div>+      'anyarray',</div><div>+    ],</div><div>+  },</div><div>+}</div><div>diff --git a/contrib/anyarray/sql/anyarray.sql b/contrib/anyarray/sql/anyarray.sql</div><div>new file mode 100644</div><div>index 00000000000..90cc061fbde</div><div>--- /dev/null</div><div>+++ b/contrib/anyarray/sql/anyarray.sql</div><div>@@ -0,0 +1,330 @@</div><div>+CREATE EXTENSION anyarray;</div><div>+</div><div>+--</div><div>+-- Phase 1: set operations, helpers and operators for int8, uuid, text</div><div>+--</div><div>+</div><div>+-- ===== int8 =====</div><div>+SELECT anyarray_sort(ARRAY[3, 1, 2, 1]::int8[]);</div><div>+SELECT anyarray_sort(ARRAY[3, 1, 2, 1]::int8[], 'desc');</div><div>+SELECT anyarray_sort(ARRAY[]::int8[]);</div><div>+SELECT anyarray_uniq(ARRAY[1, 1, 2, 3, 3, 2]::int8[]);</div><div>+SELECT anyarray_idx(ARRAY[10, 20, 30]::int8[], 20::int8);</div><div>+SELECT anyarray_idx(ARRAY[10, 20, 30]::int8[], 99::int8);</div><div>+SELECT anyarray_subarray(ARRAY[1,2,3,4,5]::int8[], 2, 2);</div><div>+SELECT anyarray_subarray(ARRAY[1,2,3,4,5]::int8[], 3);</div><div>+SELECT anyarray_subarray(ARRAY[1,2,3]::int8[], 5, 1);</div><div>+</div><div>+SELECT ARRAY[1,2,3]::int8[] &amp; ARRAY[2,3,4]::int8[];</div><div>+SELECT ARRAY[1,2,3]::int8[] | ARRAY[3,4,5]::int8[];</div><div>+SELECT ARRAY[1,2,3]::int8[] | 4::int8;</div><div>+SELECT ARRAY[1,2,3,4]::int8[] - ARRAY[2,4]::int8[];</div><div>+SELECT ARRAY[1,2,2,3,2]::int8[] - 2::int8;</div><div>+SELECT # ARRAY[10,20,30]::int8[];</div><div>+SELECT ARRAY[10,20,30]::int8[] # 20::int8;</div><div>+</div><div>+-- ===== uuid =====</div><div>+SELECT anyarray_sort(ARRAY[</div><div>+  '00000000-0000-0000-0000-000000000003'::uuid,</div><div>+  '00000000-0000-0000-0000-000000000001',</div><div>+  '00000000-0000-0000-0000-000000000002']);</div><div>+SELECT anyarray_uniq(ARRAY[</div><div>+  '00000000-0000-0000-0000-000000000001'::uuid,</div><div>+  '00000000-0000-0000-0000-000000000001',</div><div>+  '00000000-0000-0000-0000-000000000002']);</div><div>+SELECT anyarray_idx(ARRAY[</div><div>+  '00000000-0000-0000-0000-000000000001'::uuid,</div><div>+  '00000000-0000-0000-0000-000000000002'],</div><div>+  '00000000-0000-0000-0000-000000000002'::uuid);</div><div>+</div><div>+SELECT ARRAY['00000000-0000-0000-0000-000000000001'::uuid,</div><div>+             '00000000-0000-0000-0000-000000000002']</div><div>+     &amp; ARRAY['00000000-0000-0000-0000-000000000002'::uuid,</div><div>+             '00000000-0000-0000-0000-000000000003'];</div><div>+</div><div>+SELECT ARRAY['00000000-0000-0000-0000-000000000001'::uuid]</div><div>+     | '00000000-0000-0000-0000-000000000002'::uuid;</div><div>+</div><div>+-- ===== text =====</div><div>+SELECT anyarray_sort(ARRAY['banana','apple','cherry']);</div><div>+SELECT anyarray_sort(ARRAY['banana','apple','cherry'], 'desc');</div><div>+SELECT anyarray_uniq(ARRAY['a','b','a','c','b']);</div><div>+SELECT anyarray_idx(ARRAY['a','b','c'], 'b'::text);</div><div>+SELECT ARRAY['a','b','c']::text[] &amp; ARRAY['b','c','d']::text[];</div><div>+SELECT ARRAY['a','b','c']::text[] | 'd'::text;</div><div>+SELECT ARRAY['a','b','c','b']::text[] - 'b'::text;</div><div>+</div><div>+-- ===== error cases =====</div><div>+-- multi-dim</div><div>+SELECT anyarray_sort(ARRAY[[1,2],[3,4]]::int8[]);</div><div>+-- nulls</div><div>+SELECT anyarray_sort(ARRAY[1, NULL, 2]::int8[]);</div><div>+-- bad direction</div><div>+SELECT anyarray_sort(ARRAY[1,2,3]::int8[], 'bogus');</div><div>+</div><div>+--</div><div>+-- Phase 2: anyquery and @@ operator</div><div>+--</div><div>+</div><div>+-- parsing + output round-trip</div><div>+SELECT '1 &amp; 2'::anyquery::text;</div><div>+SELECT '1 &amp; 2 | 3'::anyquery::text;</div><div>+SELECT '(1 | 2) &amp; 3'::anyquery::text;</div><div>+SELECT '!1 &amp; 2'::anyquery::text;</div><div>+SELECT '!(1 | 2) &amp; 3'::anyquery::text;</div><div>+SELECT '"hello world" | foo'::anyquery::text;</div><div>+SELECT anyquery_querytree('1 &amp; 2 | 3'::anyquery);</div><div>+</div><div>+-- int8 matching</div><div>+SELECT ARRAY[1,2,3]::int8[] @@ '1'::anyquery;</div><div>+SELECT ARRAY[1,2,3]::int8[] @@ '1 &amp; 2'::anyquery;</div><div>+SELECT ARRAY[1,2,3]::int8[] @@ '1 &amp; 4'::anyquery;</div><div>+SELECT ARRAY[1,2,3]::int8[] @@ '1 | 4'::anyquery;</div><div>+SELECT ARRAY[1,2,3]::int8[] @@ '!4'::anyquery;</div><div>+SELECT ARRAY[1,2,3]::int8[] @@ '!1'::anyquery;</div><div>+SELECT ARRAY[1,2,3]::int8[] @@ '!4 &amp; 1'::anyquery;</div><div>+SELECT ARRAY[1,2,3]::int8[] @@ '(1 | 4) &amp; (2 | 5)'::anyquery;</div><div>+</div><div>+-- commutator</div><div>+SELECT '1 &amp; 2'::anyquery ~~ ARRAY[1,2,3]::int8[];</div><div>+SELECT '1 &amp; 4'::anyquery ~~ ARRAY[1,2,3]::int8[];</div><div>+</div><div>+-- uuid</div><div>+SELECT ARRAY['00000000-0000-0000-0000-000000000001'::uuid,</div><div>+             '00000000-0000-0000-0000-000000000002']</div><div>+       @@ '00000000-0000-0000-0000-000000000001 &amp; 00000000-0000-0000-0000-000000000002'::anyquery;</div><div>+SELECT ARRAY['00000000-0000-0000-0000-000000000001'::uuid]</div><div>+       @@ '00000000-0000-0000-0000-000000000002'::anyquery;</div><div>+</div><div>+-- text</div><div>+SELECT ARRAY['apple','banana','cherry']::text[] @@ 'apple &amp; banana'::anyquery;</div><div>+SELECT ARRAY['apple','banana','cherry']::text[] @@ '"banana" | grape'::anyquery;</div><div>+SELECT ARRAY['apple','banana','cherry']::text[] @@ 'durian | grape'::anyquery;</div><div>+</div><div>+-- empty array</div><div>+SELECT ARRAY[]::int8[] @@ '1'::anyquery;</div><div>+SELECT ARRAY[]::int8[] @@ '!1'::anyquery;</div><div>+</div><div>+-- parse errors</div><div>+SELECT ''::anyquery;</div><div>+SELECT '1 &amp;'::anyquery;</div><div>+SELECT '1 &amp; (2'::anyquery;</div><div>+SELECT '1 ) 2'::anyquery;</div><div>+</div><div>+-- runtime errors: token cannot be parsed as element type</div><div>+SELECT ARRAY[1,2]::int8[] @@ 'abc'::anyquery;</div><div>+</div><div>+--</div><div>+-- Phase 3: GiST signature index</div><div>+--</div><div>+</div><div>+-- amvalidate: well-formed opclass</div><div>+SELECT amname, opcname FROM pg_opclass opc</div><div>+LEFT JOIN pg_am am ON am.oid = opcmethod</div><div>+WHERE opc.opcname = 'anyarray_gist_ops' AND NOT amvalidate(opc.oid);</div><div>+</div><div>+-- int8 GiST: build deterministic table</div><div>+CREATE TABLE anyarray_gist_int8 (id int, a int8[]);</div><div>+INSERT INTO anyarray_gist_int8 VALUES</div><div>+  (1, ARRAY[1,2,3]::int8[]),</div><div>+  (2, ARRAY[10,20,30]::int8[]),</div><div>+  (3, ARRAY[10,20,30]::int8[]),</div><div>+  (4, ARRAY[1,2,3,4,5]::int8[]),</div><div>+  (5, ARRAY[100,200]::int8[]);</div><div>+</div><div>+CREATE INDEX anyarray_gist_int8_idx</div><div>+  ON anyarray_gist_int8 USING gist(a anyarray_gist_ops);</div><div>+</div><div>+SET enable_seqscan = off;</div><div>+</div><div>+SELECT id FROM anyarray_gist_int8 WHERE a @&gt; ARRAY[1,2]::int8[] ORDER BY id;</div><div>+SELECT id FROM anyarray_gist_int8 WHERE a &amp;&amp; ARRAY[10,200]::int8[] ORDER BY id;</div><div>+SELECT id FROM anyarray_gist_int8 WHERE a = ARRAY[10,20,30]::int8[] ORDER BY id;</div><div>+SELECT id FROM anyarray_gist_int8 WHERE a &lt;@ ARRAY[1,2,3,4,5]::int8[] ORDER BY id;</div><div>+SELECT id FROM anyarray_gist_int8 WHERE a @@ '10 &amp; 20'::anyquery ORDER BY id;</div><div>+SELECT id FROM anyarray_gist_int8 WHERE a @@ '1 | 100'::anyquery ORDER BY id;</div><div>+SELECT id FROM anyarray_gist_int8 WHERE a @@ '!1 &amp; 10'::anyquery ORDER BY id;</div><div>+</div><div>+-- result consistency: GiST must agree with seqscan</div><div>+SELECT (</div><div>+  SELECT count(*) FROM anyarray_gist_int8 WHERE a @&gt; ARRAY[10]::int8[]</div><div>+) = (</div><div>+  SELECT count(*) FROM (SELECT 1 FROM anyarray_gist_int8 WHERE a @&gt; ARRAY[10]::int8[]) s</div><div>+) AS gist_matches_seqscan;</div><div>+</div><div>+RESET enable_seqscan;</div><div>+</div><div>+-- text GiST</div><div>+CREATE TABLE anyarray_gist_text (id int, a text[]);</div><div>+INSERT INTO anyarray_gist_text VALUES</div><div>+  (1, ARRAY['apple','banana']),</div><div>+  (2, ARRAY['banana','cherry']),</div><div>+  (3, ARRAY['apple','cherry','durian']);</div><div>+</div><div>+CREATE INDEX anyarray_gist_text_idx</div><div>+  ON anyarray_gist_text USING gist(a anyarray_gist_ops(siglen=64));</div><div>+</div><div>+SET enable_seqscan = off;</div><div>+SELECT id FROM anyarray_gist_text WHERE a @&gt; ARRAY['apple']::text[] ORDER BY id;</div><div>+SELECT id FROM anyarray_gist_text WHERE a @@ 'apple &amp; cherry'::anyquery ORDER BY id;</div><div>+RESET enable_seqscan;</div><div>+</div><div>+-- siglen bounds</div><div>+CREATE INDEX ON anyarray_gist_text USING gist(a anyarray_gist_ops(siglen=0));</div><div>+CREATE INDEX ON anyarray_gist_text USING gist(a anyarray_gist_ops(siglen=8193));</div><div>+</div><div>+--</div><div>+-- Phase 4: GIN index (per-type, supports standard ops + @@)</div><div>+--</div><div>+</div><div>+-- amvalidate: all three opclasses</div><div>+SELECT amname, opcname FROM pg_opclass opc</div><div>+LEFT JOIN pg_am am ON am.oid = opcmethod</div><div>+WHERE opc.opcname LIKE '%anyquery_gin_ops' AND NOT amvalidate(opc.oid);</div><div>+</div><div>+-- int8 GIN</div><div>+CREATE TABLE anyarray_gin_int8 (id int, a int8[]);</div><div>+INSERT INTO anyarray_gin_int8 VALUES</div><div>+  (1, ARRAY[1,2,3]::int8[]),</div><div>+  (2, ARRAY[10,20,30]::int8[]),</div><div>+  (3, ARRAY[10,20,30]::int8[]),</div><div>+  (4, ARRAY[1,2,3,4,5]::int8[]),</div><div>+  (5, ARRAY[100,200]::int8[]);</div><div>+</div><div>+CREATE INDEX anyarray_gin_int8_idx</div><div>+  ON anyarray_gin_int8 USING gin(a int8_anyquery_gin_ops);</div><div>+</div><div>+SET enable_seqscan = off;</div><div>+SELECT id FROM anyarray_gin_int8 WHERE a @&gt; ARRAY[1,2]::int8[] ORDER BY id;</div><div>+SELECT id FROM anyarray_gin_int8 WHERE a &amp;&amp; ARRAY[10,200]::int8[] ORDER BY id;</div><div>+SELECT id FROM anyarray_gin_int8 WHERE a @@ '10 &amp; 20'::anyquery ORDER BY id;</div><div>+SELECT id FROM anyarray_gin_int8 WHERE a @@ '(1 &amp; 2) | 100'::anyquery ORDER BY id;</div><div>+SELECT id FROM anyarray_gin_int8 WHERE a @@ '!1'::anyquery ORDER BY id;</div><div>+</div><div>+-- uuid GIN</div><div>+CREATE TABLE anyarray_gin_uuid (id int, a uuid[]);</div><div>+INSERT INTO anyarray_gin_uuid VALUES</div><div>+  (1, ARRAY['11111111-1111-1111-1111-111111111111'::uuid,</div><div>+            '22222222-2222-2222-2222-222222222222']),</div><div>+  (2, ARRAY['33333333-3333-3333-3333-333333333333'::uuid]),</div><div>+  (3, ARRAY['11111111-1111-1111-1111-111111111111'::uuid,</div><div>+            '33333333-3333-3333-3333-333333333333']);</div><div>+</div><div>+CREATE INDEX anyarray_gin_uuid_idx</div><div>+  ON anyarray_gin_uuid USING gin(a uuid_anyquery_gin_ops);</div><div>+</div><div>+SET enable_seqscan = off;</div><div>+SELECT id FROM anyarray_gin_uuid</div><div>+  WHERE a @@ '11111111-1111-1111-1111-111111111111 &amp; 22222222-2222-2222-2222-222222222222'::anyquery</div><div>+  ORDER BY id;</div><div>+SELECT id FROM anyarray_gin_uuid</div><div>+  WHERE a @&gt; ARRAY['11111111-1111-1111-1111-111111111111'::uuid]</div><div>+  ORDER BY id;</div><div>+RESET enable_seqscan;</div><div>+</div><div>+-- text GIN</div><div>+CREATE TABLE anyarray_gin_text (id int, a text[]);</div><div>+INSERT INTO anyarray_gin_text VALUES</div><div>+  (1, ARRAY['apple','banana']),</div><div>+  (2, ARRAY['banana','cherry']),</div><div>+  (3, ARRAY['apple','cherry','durian']);</div><div>+</div><div>+CREATE INDEX anyarray_gin_text_idx</div><div>+  ON anyarray_gin_text USING gin(a text_anyquery_gin_ops);</div><div>+</div><div>+SET enable_seqscan = off;</div><div>+SELECT id FROM anyarray_gin_text WHERE a @@ 'apple &amp; cherry'::anyquery ORDER BY id;</div><div>+SELECT id FROM anyarray_gin_text WHERE a @@ '"durian"'::anyquery ORDER BY id;</div><div>+SELECT id FROM anyarray_gin_text WHERE a @@ 'apple | grape'::anyquery ORDER BY id;</div><div>+SELECT id FROM anyarray_gin_text WHERE a @@ '!banana'::anyquery ORDER BY id;</div><div>+RESET enable_seqscan;</div><div>+</div><div>+--</div><div>+-- Phase 5: cross-AM consistency and edge cases</div><div>+--</div><div>+-- Build a larger deterministic int8 table and index it with both GiST and</div><div>+-- GIN.  Then run each candidate query under seqscan, GiST and GIN and check</div><div>+-- that all three plans return the same row set.</div><div>+--</div><div>+</div><div>+CREATE TABLE anyarray_xcheck (id int, a int8[]);</div><div>+</div><div>+INSERT INTO anyarray_xcheck</div><div>+SELECT g,</div><div>+       ARRAY[(g % 7)::int8, ((g * 3) % 11)::int8, ((g + 1) % 5)::int8]</div><div>+FROM generate_series(1, 200) g;</div><div>+-- a few hand-picked rows to exercise common values</div><div>+INSERT INTO anyarray_xcheck VALUES</div><div>+  (1001, ARRAY[1,2,3,4,5]::int8[]),</div><div>+  (1002, ARRAY[1,2,3,4,5]::int8[]),</div><div>+  (1003, ARRAY[100,200,300]::int8[]),</div><div>+  (1004, ARRAY[]::int8[]),</div><div>+  (1005, NULL);</div><div>+</div><div>+CREATE INDEX anyarray_xcheck_gist ON anyarray_xcheck</div><div>+  USING gist(a anyarray_gist_ops);</div><div>+CREATE INDEX anyarray_xcheck_gin ON anyarray_xcheck</div><div>+  USING gin(a int8_anyquery_gin_ops);</div><div>+</div><div>+-- Run each predicate three times: pure seqscan, GiST-only, GIN-only.</div><div>+-- All three result sets must match.</div><div>+CREATE FUNCTION anyarray_xcheck_match(pred text)</div><div>+RETURNS TABLE(gist_ok bool, gin_ok bool)</div><div>+LANGUAGE plpgsql AS $$</div><div>+DECLARE</div><div>+  seq int[]; gst int[]; gin int[];</div><div>+BEGIN</div><div>+  SET LOCAL enable_seqscan = on;</div><div>+  SET LOCAL enable_indexscan = off;</div><div>+  SET LOCAL enable_bitmapscan = off;</div><div>+  EXECUTE 'SELECT array_agg(id ORDER BY id) FROM anyarray_xcheck WHERE '</div><div>+          || pred INTO seq;</div><div>+</div><div>+  -- Force GiST by hiding the GIN index.</div><div>+  ALTER INDEX anyarray_xcheck_gin SET (fastupdate = off);</div><div>+  SET LOCAL enable_seqscan = off;</div><div>+  SET LOCAL enable_indexscan = on;</div><div>+  SET LOCAL enable_bitmapscan = on;</div><div>+  DROP INDEX anyarray_xcheck_gin;</div><div>+  EXECUTE 'SELECT array_agg(id ORDER BY id) FROM anyarray_xcheck WHERE '</div><div>+          || pred INTO gst;</div><div>+  CREATE INDEX anyarray_xcheck_gin ON anyarray_xcheck</div><div>+    USING gin(a int8_anyquery_gin_ops);</div><div>+</div><div>+  -- Force GIN by hiding GiST.</div><div>+  DROP INDEX anyarray_xcheck_gist;</div><div>+  EXECUTE 'SELECT array_agg(id ORDER BY id) FROM anyarray_xcheck WHERE '</div><div>+          || pred INTO gin;</div><div>+  CREATE INDEX anyarray_xcheck_gist ON anyarray_xcheck</div><div>+    USING gist(a anyarray_gist_ops);</div><div>+</div><div>+  gist_ok := seq IS NOT DISTINCT FROM gst;</div><div>+  gin_ok  := seq IS NOT DISTINCT FROM gin;</div><div>+  RETURN NEXT;</div><div>+END $$;</div><div>+</div><div>+SELECT pred, gist_ok, gin_ok FROM (VALUES</div><div>+  ('a @&gt; ARRAY[1,2]::int8[]'),</div><div>+  ('a @&gt; ARRAY[100,200]::int8[]'),</div><div>+  ('a &amp;&amp; ARRAY[5,99]::int8[]'),</div><div>+  ('a = ARRAY[1,2,3,4,5]::int8[]'),</div><div>+  ('a @@ ''1 &amp; 2''::anyquery'),</div><div>+  ('a @@ ''100 | 999''::anyquery'),</div><div>+  ('a @@ ''!1 &amp; 2''::anyquery')</div><div>+) v(pred), LATERAL anyarray_xcheck_match(pred);</div><div>+</div><div>+-- Edge cases: empty / NULL arrays via index</div><div>+SET enable_seqscan = off;</div><div>+SELECT id FROM anyarray_xcheck WHERE a @&gt; ARRAY[]::int8[] AND id = 1004;</div><div>+SELECT id FROM anyarray_xcheck WHERE a &lt;@ ARRAY[1,2,3]::int8[] AND id &lt; 100 ORDER BY id LIMIT 3;</div><div>+SELECT count(*) FROM anyarray_xcheck WHERE a IS NULL;</div><div>+RESET enable_seqscan;</div><div>+</div><div>+-- DELETE / VACUUM / re-query through index</div><div>+DELETE FROM anyarray_xcheck WHERE id BETWEEN 1 AND 50;</div><div>+VACUUM anyarray_xcheck;</div><div>+SET enable_seqscan = off;</div><div>+SELECT count(*) FROM anyarray_xcheck WHERE a @@ '1 | 2'::anyquery;</div><div>+RESET enable_seqscan;</div><div>+</div><div>+DROP FUNCTION anyarray_xcheck_match(text);</div><div>diff --git a/contrib/meson.build b/contrib/meson.build</div><div>index ebb7f83d8c5..e158f18fa7e 100644</div><div>--- a/contrib/meson.build</div><div>+++ b/contrib/meson.build</div><div>@@ -13,6 +13,7 @@ contrib_doc_args = {<!-- --></div><div> }</div><div> </div><div> subdir('amcheck')</div><div>+subdir('anyarray')</div><div> subdir('auth_delay')</div><div> subdir('auto_explain')</div><div> subdir('basic_archive')</div><div>diff --git a/doc/src/sgml/anyarray.sgml b/doc/src/sgml/anyarray.sgml</div><div>new file mode 100644</div><div>index 00000000000..4f376e0868c</div><div>--- /dev/null</div><div>+++ b/doc/src/sgml/anyarray.sgml</div><div>@@ -0,0 +1,482 @@</div><div>+&lt;!-- doc/src/sgml/anyarray.sgml --&gt;</div><div>+</div><div>+&lt;sect1 id="anyarray" xreflabel="anyarray"&gt;</div><div>+ &lt;title&gt;anyarray &amp;mdash; operations and indexes for arrays of any type&lt;/title&gt;</div><div>+</div><div>+ &lt;indexterm zone="anyarray"&gt;</div><div>+  &lt;primary&gt;anyarray&lt;/primary&gt;</div><div>+ &lt;/indexterm&gt;</div><div>+</div><div>+ &lt;para&gt;</div><div>+  The &lt;filename&gt;anyarray&lt;/filename&gt; module generalizes</div><div>+  &lt;xref linkend="intarray"/&gt;-style operations to arrays of any element type</div><div>+  that provides a default B-tree opclass.  It adds set-style helpers, a</div><div>+  textual boolean query type (&lt;type&gt;anyquery&lt;/type&gt;), and index support that</div><div>+  works for arbitrary element types.</div><div>+ &lt;/para&gt;</div><div>+</div><div>+ &lt;para&gt;</div><div>+  All operations reject arrays that contain &lt;literal&gt;NULL&lt;/literal&gt; elements,</div><div>+  and they are defined only for one-dimensional arrays.</div><div>+ &lt;/para&gt;</div><div>+</div><div>+ &lt;para&gt;</div><div>+  This module is not marked as &lt;quote&gt;trusted&lt;/quote&gt;: installing it</div><div>+  requires database-level privileges, because the index operator classes</div><div>+  it defines refer to internal storage types.</div><div>+ &lt;/para&gt;</div><div>+</div><div>+ &lt;sect2 id="anyarray-funcs-ops"&gt;</div><div>+  &lt;title&gt;&lt;filename&gt;anyarray&lt;/filename&gt; Functions and Operators&lt;/title&gt;</div><div>+</div><div>+  &lt;para&gt;</div><div>+   The functions provided by &lt;filename&gt;anyarray&lt;/filename&gt; are listed in</div><div>+   &lt;xref linkend="anyarray-func-table"/&gt;, the operators in</div><div>+   &lt;xref linkend="anyarray-op-table"/&gt;.</div><div>+  &lt;/para&gt;</div><div>+</div><div>+  &lt;table id="anyarray-func-table"&gt;</div><div>+   &lt;title&gt;&lt;filename&gt;anyarray&lt;/filename&gt; Functions&lt;/title&gt;</div><div>+    &lt;tgroup cols="1"&gt;</div><div>+     &lt;thead&gt;</div><div>+      &lt;row&gt;</div><div>+       &lt;entry role="func_table_entry"&gt;&lt;para role="func_signature"&gt;</div><div>+        Function</div><div>+       &lt;/para&gt;</div><div>+       &lt;para&gt;</div><div>+        Description</div><div>+       &lt;/para&gt;</div><div>+       &lt;para&gt;</div><div>+        Example(s)</div><div>+       &lt;/para&gt;&lt;/entry&gt;</div><div>+      &lt;/row&gt;</div><div>+     &lt;/thead&gt;</div><div>+</div><div>+     &lt;tbody&gt;</div><div>+      &lt;row&gt;</div><div>+       &lt;entry role="func_table_entry"&gt;&lt;para role="func_signature"&gt;</div><div>+        &lt;function&gt;anyarray_sort&lt;/function&gt; ( &lt;type&gt;anyarray&lt;/type&gt; [, &lt;type&gt;text&lt;/type&gt; ] )</div><div>+        &lt;returnvalue&gt;anyarray&lt;/returnvalue&gt;</div><div>+       &lt;/para&gt;</div><div>+       &lt;para&gt;</div><div>+        Sorts an array.  The optional second argument is</div><div>+        &lt;literal&gt;asc&lt;/literal&gt; (default) or &lt;literal&gt;desc&lt;/literal&gt;.</div><div>+       &lt;/para&gt;</div><div>+       &lt;para&gt;</div><div>+        &lt;literal&gt;anyarray_sort('{3,1,2}'::int8[])&lt;/literal&gt;</div><div>+        &lt;returnvalue&gt;{1,2,3}&lt;/returnvalue&gt;</div><div>+       &lt;/para&gt;&lt;/entry&gt;</div><div>+      &lt;/row&gt;</div><div>+</div><div>+      &lt;row&gt;</div><div>+       &lt;entry role="func_table_entry"&gt;&lt;para role="func_signature"&gt;</div><div>+        &lt;function&gt;anyarray_uniq&lt;/function&gt; ( &lt;type&gt;anyarray&lt;/type&gt; )</div><div>+        &lt;returnvalue&gt;anyarray&lt;/returnvalue&gt;</div><div>+       &lt;/para&gt;</div><div>+       &lt;para&gt;</div><div>+        Removes duplicates from the array, returning the sorted unique</div><div>+        elements.</div><div>+       &lt;/para&gt;</div><div>+       &lt;para&gt;</div><div>+        &lt;literal&gt;anyarray_uniq('{1,1,2,3,3}'::int8[])&lt;/literal&gt;</div><div>+        &lt;returnvalue&gt;{1,2,3}&lt;/returnvalue&gt;</div><div>+       &lt;/para&gt;&lt;/entry&gt;</div><div>+      &lt;/row&gt;</div><div>+</div><div>+      &lt;row&gt;</div><div>+       &lt;entry role="func_table_entry"&gt;&lt;para role="func_signature"&gt;</div><div>+        &lt;function&gt;anyarray_idx&lt;/function&gt; ( &lt;type&gt;anyarray&lt;/type&gt;, &lt;type&gt;anyelement&lt;/type&gt; )</div><div>+        &lt;returnvalue&gt;integer&lt;/returnvalue&gt;</div><div>+       &lt;/para&gt;</div><div>+       &lt;para&gt;</div><div>+        Returns the 1-based index of the first occurrence of the element,</div><div>+        or 0 if not found.</div><div>+       &lt;/para&gt;</div><div>+       &lt;para&gt;</div><div>+        &lt;literal&gt;anyarray_idx(ARRAY['a','b','c'], 'b')&lt;/literal&gt;</div><div>+        &lt;returnvalue&gt;2&lt;/returnvalue&gt;</div><div>+       &lt;/para&gt;&lt;/entry&gt;</div><div>+      &lt;/row&gt;</div><div>+</div><div>+      &lt;row&gt;</div><div>+       &lt;entry role="func_table_entry"&gt;&lt;para role="func_signature"&gt;</div><div>+        &lt;function&gt;anyarray_subarray&lt;/function&gt; ( &lt;type&gt;anyarray&lt;/type&gt;, &lt;parameter&gt;start&lt;/parameter&gt; &lt;type&gt;integer&lt;/type&gt; [, &lt;parameter&gt;length&lt;/parameter&gt; &lt;type&gt;integer&lt;/type&gt; ] )</div><div>+        &lt;returnvalue&gt;anyarray&lt;/returnvalue&gt;</div><div>+       &lt;/para&gt;</div><div>+       &lt;para&gt;</div><div>+        Returns a contiguous slice starting at &lt;parameter&gt;start&lt;/parameter&gt;</div><div>+        (1-based).  If &lt;parameter&gt;length&lt;/parameter&gt; is omitted the slice</div><div>+        extends to the end of the array.  Out-of-range positions or</div><div>+        non-positive lengths produce an empty array.</div><div>+       &lt;/para&gt;</div><div>+       &lt;para&gt;</div><div>+        &lt;literal&gt;anyarray_subarray('{1,2,3,4,5}'::int8[], 2, 2)&lt;/literal&gt;</div><div>+        &lt;returnvalue&gt;{2,3}&lt;/returnvalue&gt;</div><div>+       &lt;/para&gt;&lt;/entry&gt;</div><div>+      &lt;/row&gt;</div><div>+</div><div>+      &lt;row&gt;</div><div>+       &lt;entry role="func_table_entry"&gt;&lt;para role="func_signature"&gt;</div><div>+        &lt;function&gt;anyarray_icount&lt;/function&gt; ( &lt;type&gt;anyarray&lt;/type&gt; )</div><div>+        &lt;returnvalue&gt;integer&lt;/returnvalue&gt;</div><div>+       &lt;/para&gt;</div><div>+       &lt;para&gt;</div><div>+        Returns the number of elements in the array (exposed under the</div><div>+        &lt;literal&gt;#&lt;/literal&gt; operator).</div><div>+       &lt;/para&gt;</div><div>+       &lt;para&gt;</div><div>+        &lt;literal&gt;anyarray_icount('{10,20,30}'::int8[])&lt;/literal&gt;</div><div>+        &lt;returnvalue&gt;3&lt;/returnvalue&gt;</div><div>+       &lt;/para&gt;&lt;/entry&gt;</div><div>+      &lt;/row&gt;</div><div>+</div><div>+      &lt;row&gt;</div><div>+       &lt;entry role="func_table_entry"&gt;&lt;para role="func_signature"&gt;</div><div>+        &lt;function&gt;anyarray_intersect&lt;/function&gt; ( &lt;type&gt;anyarray&lt;/type&gt;, &lt;type&gt;anyarray&lt;/type&gt; )</div><div>+        &lt;returnvalue&gt;anyarray&lt;/returnvalue&gt;</div><div>+       &lt;/para&gt;</div><div>+       &lt;para&gt;</div><div>+        Returns the sorted, deduplicated values present in both inputs.</div><div>+       &lt;/para&gt;</div><div>+       &lt;para&gt;</div><div>+        &lt;literal&gt;anyarray_intersect('{1,2,3}'::int8[], '{2,3,4}')&lt;/literal&gt;</div><div>+        &lt;returnvalue&gt;{2,3}&lt;/returnvalue&gt;</div><div>+       &lt;/para&gt;&lt;/entry&gt;</div><div>+      &lt;/row&gt;</div><div>+</div><div>+      &lt;row&gt;</div><div>+       &lt;entry role="func_table_entry"&gt;&lt;para role="func_signature"&gt;</div><div>+        &lt;function&gt;anyarray_union&lt;/function&gt; ( &lt;type&gt;anyarray&lt;/type&gt;, &lt;type&gt;anyarray&lt;/type&gt; )</div><div>+        &lt;returnvalue&gt;anyarray&lt;/returnvalue&gt;</div><div>+       &lt;/para&gt;</div><div>+       &lt;para&gt;</div><div>+        Returns the sorted, deduplicated union of both inputs.</div><div>+       &lt;/para&gt;</div><div>+       &lt;para&gt;</div><div>+        &lt;literal&gt;anyarray_union('{1,2}'::int8[], '{2,3}')&lt;/literal&gt;</div><div>+        &lt;returnvalue&gt;{1,2,3}&lt;/returnvalue&gt;</div><div>+       &lt;/para&gt;&lt;/entry&gt;</div><div>+      &lt;/row&gt;</div><div>+</div><div>+      &lt;row&gt;</div><div>+       &lt;entry role="func_table_entry"&gt;&lt;para role="func_signature"&gt;</div><div>+        &lt;function&gt;anyarray_union_elem&lt;/function&gt; ( &lt;type&gt;anyarray&lt;/type&gt;, &lt;type&gt;anyelement&lt;/type&gt; )</div><div>+        &lt;returnvalue&gt;anyarray&lt;/returnvalue&gt;</div><div>+       &lt;/para&gt;</div><div>+       &lt;para&gt;</div><div>+        Adds an element to the array if not already present; result is</div><div>+        sorted and deduplicated.</div><div>+       &lt;/para&gt;</div><div>+       &lt;para&gt;</div><div>+        &lt;literal&gt;anyarray_union_elem('{1,2,3}'::int8[], 4::int8)&lt;/literal&gt;</div><div>+        &lt;returnvalue&gt;{1,2,3,4}&lt;/returnvalue&gt;</div><div>+       &lt;/para&gt;&lt;/entry&gt;</div><div>+      &lt;/row&gt;</div><div>+</div><div>+      &lt;row&gt;</div><div>+       &lt;entry role="func_table_entry"&gt;&lt;para role="func_signature"&gt;</div><div>+        &lt;function&gt;anyarray_difference&lt;/function&gt; ( &lt;type&gt;anyarray&lt;/type&gt;, &lt;type&gt;anyarray&lt;/type&gt; )</div><div>+        &lt;returnvalue&gt;anyarray&lt;/returnvalue&gt;</div><div>+       &lt;/para&gt;</div><div>+       &lt;para&gt;</div><div>+        Returns the sorted, deduplicated values from the first array that</div><div>+        are not in the second.</div><div>+       &lt;/para&gt;</div><div>+       &lt;para&gt;</div><div>+        &lt;literal&gt;anyarray_difference('{1,2,3,4}'::int8[], '{2,4}')&lt;/literal&gt;</div><div>+        &lt;returnvalue&gt;{1,3}&lt;/returnvalue&gt;</div><div>+       &lt;/para&gt;&lt;/entry&gt;</div><div>+      &lt;/row&gt;</div><div>+</div><div>+      &lt;row&gt;</div><div>+       &lt;entry role="func_table_entry"&gt;&lt;para role="func_signature"&gt;</div><div>+        &lt;function&gt;anyarray_difference_elem&lt;/function&gt; ( &lt;type&gt;anyarray&lt;/type&gt;, &lt;type&gt;anyelement&lt;/type&gt; )</div><div>+        &lt;returnvalue&gt;anyarray&lt;/returnvalue&gt;</div><div>+       &lt;/para&gt;</div><div>+       &lt;para&gt;</div><div>+        Removes all occurrences of the given element, preserving the</div><div>+        relative order of the surviving elements.</div><div>+       &lt;/para&gt;</div><div>+       &lt;para&gt;</div><div>+        &lt;literal&gt;anyarray_difference_elem('{1,2,2,3,2}'::int8[], 2::int8)&lt;/literal&gt;</div><div>+        &lt;returnvalue&gt;{1,3}&lt;/returnvalue&gt;</div><div>+       &lt;/para&gt;&lt;/entry&gt;</div><div>+      &lt;/row&gt;</div><div>+</div><div>+      &lt;row&gt;</div><div>+       &lt;entry role="func_table_entry"&gt;&lt;para role="func_signature"&gt;</div><div>+        &lt;function&gt;anyquery_querytree&lt;/function&gt; ( &lt;type&gt;anyquery&lt;/type&gt; )</div><div>+        &lt;returnvalue&gt;text&lt;/returnvalue&gt;</div><div>+       &lt;/para&gt;</div><div>+       &lt;para&gt;</div><div>+        Returns the query in postfix form; useful for debugging.</div><div>+       &lt;/para&gt;</div><div>+       &lt;para&gt;</div><div>+        &lt;literal&gt;anyquery_querytree('1 &amp;amp; 2 | 3'::anyquery)&lt;/literal&gt;</div><div>+        &lt;returnvalue&gt;1 2 &amp;amp; 3 |&lt;/returnvalue&gt;</div><div>+       &lt;/para&gt;&lt;/entry&gt;</div><div>+      &lt;/row&gt;</div><div>+     &lt;/tbody&gt;</div><div>+    &lt;/tgroup&gt;</div><div>+   &lt;/table&gt;</div><div>+</div><div>+   &lt;table id="anyarray-op-table"&gt;</div><div>+    &lt;title&gt;&lt;filename&gt;anyarray&lt;/filename&gt; Operators&lt;/title&gt;</div><div>+     &lt;tgroup cols="1"&gt;</div><div>+      &lt;thead&gt;</div><div>+       &lt;row&gt;</div><div>+        &lt;entry role="func_table_entry"&gt;&lt;para role="func_signature"&gt;</div><div>+         Operator</div><div>+        &lt;/para&gt;</div><div>+        &lt;para&gt;</div><div>+         Description</div><div>+        &lt;/para&gt;&lt;/entry&gt;</div><div>+       &lt;/row&gt;</div><div>+      &lt;/thead&gt;</div><div>+</div><div>+      &lt;tbody&gt;</div><div>+       &lt;row&gt;</div><div>+        &lt;entry role="func_table_entry"&gt;&lt;para role="func_signature"&gt;</div><div>+         &lt;type&gt;&lt;/type&gt; &lt;literal&gt;#&lt;/literal&gt; &lt;type&gt;anyarray&lt;/type&gt;</div><div>+         &lt;returnvalue&gt;integer&lt;/returnvalue&gt;</div><div>+        &lt;/para&gt;</div><div>+        &lt;para&gt;</div><div>+         Returns the number of elements in the array (prefix operator).</div><div>+        &lt;/para&gt;&lt;/entry&gt;</div><div>+       &lt;/row&gt;</div><div>+</div><div>+       &lt;row&gt;</div><div>+        &lt;entry role="func_table_entry"&gt;&lt;para role="func_signature"&gt;</div><div>+         &lt;type&gt;anyarray&lt;/type&gt; &lt;literal&gt;#&lt;/literal&gt; &lt;type&gt;anyelement&lt;/type&gt;</div><div>+         &lt;returnvalue&gt;integer&lt;/returnvalue&gt;</div><div>+        &lt;/para&gt;</div><div>+        &lt;para&gt;</div><div>+         Returns the 1-based index of the right operand in the array, or 0</div><div>+         if not found.  Same as &lt;function&gt;anyarray_idx&lt;/function&gt;.</div><div>+        &lt;/para&gt;&lt;/entry&gt;</div><div>+       &lt;/row&gt;</div><div>+</div><div>+       &lt;row&gt;</div><div>+        &lt;entry role="func_table_entry"&gt;&lt;para role="func_signature"&gt;</div><div>+         &lt;type&gt;anyarray&lt;/type&gt; &lt;literal&gt;&amp;amp;&lt;/literal&gt; &lt;type&gt;anyarray&lt;/type&gt;</div><div>+         &lt;returnvalue&gt;anyarray&lt;/returnvalue&gt;</div><div>+        &lt;/para&gt;</div><div>+        &lt;para&gt;</div><div>+         Set intersection of the operands.</div><div>+        &lt;/para&gt;&lt;/entry&gt;</div><div>+       &lt;/row&gt;</div><div>+</div><div>+       &lt;row&gt;</div><div>+        &lt;entry role="func_table_entry"&gt;&lt;para role="func_signature"&gt;</div><div>+         &lt;type&gt;anyarray&lt;/type&gt; &lt;literal&gt;|&lt;/literal&gt; &lt;type&gt;anyarray&lt;/type&gt;</div><div>+         &lt;returnvalue&gt;anyarray&lt;/returnvalue&gt;</div><div>+        &lt;/para&gt;</div><div>+        &lt;para&gt;</div><div>+         Set union of the operands.</div><div>+        &lt;/para&gt;&lt;/entry&gt;</div><div>+       &lt;/row&gt;</div><div>+</div><div>+       &lt;row&gt;</div><div>+        &lt;entry role="func_table_entry"&gt;&lt;para role="func_signature"&gt;</div><div>+         &lt;type&gt;anyarray&lt;/type&gt; &lt;literal&gt;|&lt;/literal&gt; &lt;type&gt;anyelement&lt;/type&gt;</div><div>+         &lt;returnvalue&gt;anyarray&lt;/returnvalue&gt;</div><div>+        &lt;/para&gt;</div><div>+        &lt;para&gt;</div><div>+         Adds the right operand to the array if not already present.</div><div>+        &lt;/para&gt;&lt;/entry&gt;</div><div>+       &lt;/row&gt;</div><div>+</div><div>+       &lt;row&gt;</div><div>+        &lt;entry role="func_table_entry"&gt;&lt;para role="func_signature"&gt;</div><div>+         &lt;type&gt;anyarray&lt;/type&gt; &lt;literal&gt;-&lt;/literal&gt; &lt;type&gt;anyarray&lt;/type&gt;</div><div>+         &lt;returnvalue&gt;anyarray&lt;/returnvalue&gt;</div><div>+        &lt;/para&gt;</div><div>+        &lt;para&gt;</div><div>+         Set difference: elements of the left array not present in the</div><div>+         right.</div><div>+        &lt;/para&gt;&lt;/entry&gt;</div><div>+       &lt;/row&gt;</div><div>+</div><div>+       &lt;row&gt;</div><div>+        &lt;entry role="func_table_entry"&gt;&lt;para role="func_signature"&gt;</div><div>+         &lt;type&gt;anyarray&lt;/type&gt; &lt;literal&gt;-&lt;/literal&gt; &lt;type&gt;anyelement&lt;/type&gt;</div><div>+         &lt;returnvalue&gt;anyarray&lt;/returnvalue&gt;</div><div>+        &lt;/para&gt;</div><div>+        &lt;para&gt;</div><div>+         Removes all occurrences of the right operand from the array.</div><div>+        &lt;/para&gt;&lt;/entry&gt;</div><div>+       &lt;/row&gt;</div><div>+</div><div>+       &lt;row&gt;</div><div>+        &lt;entry role="func_table_entry"&gt;&lt;para role="func_signature"&gt;</div><div>+         &lt;type&gt;anyarray&lt;/type&gt; &lt;literal&gt;@@&lt;/literal&gt; &lt;type&gt;anyquery&lt;/type&gt;</div><div>+         &lt;returnvalue&gt;boolean&lt;/returnvalue&gt;</div><div>+        &lt;/para&gt;</div><div>+        &lt;para&gt;</div><div>+         True if the array satisfies the query (see below).</div><div>+        &lt;/para&gt;&lt;/entry&gt;</div><div>+       &lt;/row&gt;</div><div>+</div><div>+       &lt;row&gt;</div><div>+        &lt;entry role="func_table_entry"&gt;&lt;para role="func_signature"&gt;</div><div>+         &lt;type&gt;anyquery&lt;/type&gt; &lt;literal&gt;~~&lt;/literal&gt; &lt;type&gt;anyarray&lt;/type&gt;</div><div>+         &lt;returnvalue&gt;boolean&lt;/returnvalue&gt;</div><div>+        &lt;/para&gt;</div><div>+        &lt;para&gt;</div><div>+         Commutator of &lt;literal&gt;@@&lt;/literal&gt;.</div><div>+        &lt;/para&gt;&lt;/entry&gt;</div><div>+       &lt;/row&gt;</div><div>+      &lt;/tbody&gt;</div><div>+     &lt;/tgroup&gt;</div><div>+   &lt;/table&gt;</div><div>+</div><div>+   &lt;para&gt;</div><div>+    The operators &lt;literal&gt;&amp;amp;&amp;amp;&lt;/literal&gt;, &lt;literal&gt;@&amp;gt;&lt;/literal&gt;,</div><div>+    &lt;literal&gt;&amp;lt;@&lt;/literal&gt; and &lt;literal&gt;=&lt;/literal&gt; on arrays are</div><div>+    &lt;emphasis&gt;not&lt;/emphasis&gt; redefined by this extension; the built-in</div><div>+    PostgreSQL operators are used.</div><div>+   &lt;/para&gt;</div><div>+ &lt;/sect2&gt;</div><div>+</div><div>+ &lt;sect2 id="anyarray-query"&gt;</div><div>+  &lt;title&gt;The &lt;type&gt;anyquery&lt;/type&gt; Type&lt;/title&gt;</div><div>+</div><div>+  &lt;para&gt;</div><div>+   &lt;type&gt;anyquery&lt;/type&gt; represents a boolean expression over array</div><div>+   elements.  Values are textual tokens; the element type used to interpret</div><div>+   them is determined by the left-hand side of &lt;literal&gt;@@&lt;/literal&gt; at</div><div>+   query time.  Tokens are combined with the operators</div><div>+   &lt;literal&gt;&amp;amp;&lt;/literal&gt; (AND), &lt;literal&gt;|&lt;/literal&gt; (OR) and</div><div>+   &lt;literal&gt;!&lt;/literal&gt; (NOT).  Parentheses control precedence; without</div><div>+   them &lt;literal&gt;&amp;amp;&lt;/literal&gt; binds tighter than &lt;literal&gt;|&lt;/literal&gt;.</div><div>+  &lt;/para&gt;</div><div>+</div><div>+  &lt;para&gt;</div><div>+   A token consists of any sequence of characters that are not whitespace</div><div>+   or one of &lt;literal&gt;&amp;amp; | ! ( ) "&lt;/literal&gt;.  To include those</div><div>+   characters or embedded whitespace, wrap the token in double quotes:</div><div>+   &lt;literal&gt;"hello world"&lt;/literal&gt;.  Inside quotes, a backslash escapes</div><div>+   the next character.</div><div>+  &lt;/para&gt;</div><div>+</div><div>+  &lt;para&gt;</div><div>+   At evaluation time, each token is parsed by the input function of the</div><div>+   array's element type.  This means</div><div>+   &lt;literal&gt;'1 &amp;amp; 2'::anyquery @@ ARRAY[1,2,3]::bigint[]&lt;/literal&gt;</div><div>+   parses &lt;quote&gt;1&lt;/quote&gt; and &lt;quote&gt;2&lt;/quote&gt; as &lt;type&gt;bigint&lt;/type&gt;; the</div><div>+   same query against a &lt;type&gt;text[]&lt;/type&gt; column compares the literal</div><div>+   strings &lt;quote&gt;1&lt;/quote&gt; and &lt;quote&gt;2&lt;/quote&gt;.  An unparseable token</div><div>+   raises an error at &lt;literal&gt;@@&lt;/literal&gt;-time, not at parse time.</div><div>+  &lt;/para&gt;</div><div>+ &lt;/sect2&gt;</div><div>+</div><div>+ &lt;sect2 id="anyarray-index"&gt;</div><div>+  &lt;title&gt;Index Support&lt;/title&gt;</div><div>+</div><div>+  &lt;para&gt;</div><div>+   &lt;filename&gt;anyarray&lt;/filename&gt; provides a polymorphic GiST opclass and</div><div>+   per-element-type GIN opclasses.  All of them support the standard array</div><div>+   operators (&lt;literal&gt;&amp;amp;&amp;amp;&lt;/literal&gt;, &lt;literal&gt;@&amp;gt;&lt;/literal&gt;,</div><div>+   &lt;literal&gt;&amp;lt;@&lt;/literal&gt;, &lt;literal&gt;=&lt;/literal&gt;) as well as</div><div>+   &lt;literal&gt;@@&lt;/literal&gt;.</div><div>+  &lt;/para&gt;</div><div>+</div><div>+  &lt;sect3 id="anyarray-index-gist"&gt;</div><div>+   &lt;title&gt;GiST: &lt;literal&gt;anyarray_gist_ops&lt;/literal&gt;&lt;/title&gt;</div><div>+</div><div>+   &lt;para&gt;</div><div>+    A single opclass on &lt;type&gt;anyarray&lt;/type&gt; works for any element type</div><div>+    that has a default hash function.  Each indexed array is summarised as</div><div>+    a fixed-size bit vector by hashing every element into one bit; internal</div><div>+    nodes store the union of their children.  All matches are rechecked</div><div>+    because signatures are lossy.</div><div>+   &lt;/para&gt;</div><div>+</div><div>+   &lt;para&gt;</div><div>+    The optional integer parameter &lt;literal&gt;siglen&lt;/literal&gt; sets the</div><div>+    signature length in bytes.  The default is 252 bytes (2016 bits);</div><div>+    valid values are between 1 and the index-key size limit.  Longer</div><div>+    signatures produce more precise indexes at the cost of more storage.</div><div>+   &lt;/para&gt;</div><div>+</div><div>+   &lt;programlisting&gt;</div><div>+CREATE INDEX my_idx ON my_table USING gist (col anyarray_gist_ops);</div><div>+CREATE INDEX my_idx ON my_table USING gist (col anyarray_gist_ops(siglen=64));</div><div>+   &lt;/programlisting&gt;</div><div>+  &lt;/sect3&gt;</div><div>+</div><div>+  &lt;sect3 id="anyarray-index-gin"&gt;</div><div>+   &lt;title&gt;GIN: per-type opclasses&lt;/title&gt;</div><div>+</div><div>+   &lt;para&gt;</div><div>+    Because the GIN extractQuery API does not expose the indexed column's</div><div>+    element type when the query is an &lt;type&gt;anyquery&lt;/type&gt;, GIN support</div><div>+    is provided as one opclass per concrete element type.  Currently</div><div>+    supplied:</div><div>+   &lt;/para&gt;</div><div>+</div><div>+   &lt;itemizedlist&gt;</div><div>+    &lt;listitem&gt;&lt;para&gt;</div><div>+     &lt;literal&gt;int8_anyquery_gin_ops&lt;/literal&gt; for &lt;type&gt;bigint[]&lt;/type&gt;</div><div>+    &lt;/para&gt;&lt;/listitem&gt;</div><div>+    &lt;listitem&gt;&lt;para&gt;</div><div>+     &lt;literal&gt;uuid_anyquery_gin_ops&lt;/literal&gt; for &lt;type&gt;uuid[]&lt;/type&gt;</div><div>+    &lt;/para&gt;&lt;/listitem&gt;</div><div>+    &lt;listitem&gt;&lt;para&gt;</div><div>+     &lt;literal&gt;text_anyquery_gin_ops&lt;/literal&gt; for &lt;type&gt;text[]&lt;/type&gt;</div><div>+    &lt;/para&gt;&lt;/listitem&gt;</div><div>+   &lt;/itemizedlist&gt;</div><div>+</div><div>+   &lt;para&gt;</div><div>+    These opclasses are drop-in replacements for the built-in</div><div>+    &lt;literal&gt;array_ops&lt;/literal&gt;; they additionally support</div><div>+    &lt;literal&gt;@@&lt;/literal&gt;.</div><div>+   &lt;/para&gt;</div><div>+</div><div>+   &lt;programlisting&gt;</div><div>+CREATE INDEX my_idx ON my_table USING gin (col int8_anyquery_gin_ops);</div><div>+   &lt;/programlisting&gt;</div><div>+</div><div>+   &lt;para&gt;</div><div>+    For element types not in the list above, use the built-in GIN</div><div>+    &lt;literal&gt;array_ops&lt;/literal&gt; for set queries and rely on</div><div>+    &lt;literal&gt;anyarray_gist_ops&lt;/literal&gt; for &lt;literal&gt;@@&lt;/literal&gt;.</div><div>+   &lt;/para&gt;</div><div>+  &lt;/sect3&gt;</div><div>+ &lt;/sect2&gt;</div><div>+</div><div>+ &lt;sect2 id="anyarray-example"&gt;</div><div>+  &lt;title&gt;Example&lt;/title&gt;</div><div>+</div><div>+&lt;programlisting&gt;</div><div>+CREATE EXTENSION anyarray;</div><div>+</div><div>+CREATE TABLE message (mid INT PRIMARY KEY, tags TEXT[]);</div><div>+</div><div>+CREATE INDEX message_tags_gist ON message USING gist (tags anyarray_gist_ops);</div><div>+CREATE INDEX message_tags_gin  ON message USING gin  (tags text_anyquery_gin_ops);</div><div>+</div><div>+-- Messages tagged with both 'urgent' and 'bug':</div><div>+SELECT mid FROM message WHERE tags @&amp;gt; ARRAY['urgent','bug'];</div><div>+</div><div>+-- Same, with the query syntax:</div><div>+SELECT mid FROM message WHERE tags @@ 'urgent &amp;amp; bug'::anyquery;</div><div>+</div><div>+-- Messages tagged 'urgent' but not 'wontfix':</div><div>+SELECT mid FROM message WHERE tags @@ 'urgent &amp;amp; !wontfix'::anyquery;</div><div>+</div><div>+-- Sort and deduplicate a tag list:</div><div>+SELECT anyarray_uniq(tags) FROM message WHERE mid = 42;</div><div>+&lt;/programlisting&gt;</div><div>+ &lt;/sect2&gt;</div><div>+</div><div>+ &lt;sect2 id="anyarray-authors"&gt;</div><div>+  &lt;title&gt;Authors&lt;/title&gt;</div><div>+</div><div>+  &lt;para&gt;</div><div>+   The &lt;filename&gt;anyarray&lt;/filename&gt; module is a generalization of</div><div>+   &lt;xref linkend="intarray"/&gt; by Teodor Sigaev and Oleg Bartunov.</div><div>+  &lt;/para&gt;</div><div>+ &lt;/sect2&gt;</div><div>+</div><div>+&lt;/sect1&gt;</div><div>diff --git a/doc/src/sgml/contrib.sgml b/doc/src/sgml/contrib.sgml</div><div>index b9b03654aad..c9aaf79cb69 100644</div><div>--- a/doc/src/sgml/contrib.sgml</div><div>+++ b/doc/src/sgml/contrib.sgml</div><div>@@ -128,6 +128,7 @@ CREATE EXTENSION &lt;replaceable&gt;extension_name&lt;/replaceable&gt;;</div><div>  &lt;/para&gt;</div><div> </div><div>  &amp;amcheck;</div><div>+ &amp;anyarray;</div><div>  &amp;auth-delay;</div><div>  &amp;auto-explain;</div><div>  &amp;basebackup-to-shell;</div><div>diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml</div><div>index 25a85082759..0530342e74b 100644</div><div>--- a/doc/src/sgml/filelist.sgml</div><div>+++ b/doc/src/sgml/filelist.sgml</div><div>@@ -119,6 +119,7 @@</div><div> &lt;!-- contrib information --&gt;</div><div> &lt;!ENTITY contrib         SYSTEM "contrib.sgml"&gt;</div><div> &lt;!ENTITY amcheck         SYSTEM "amcheck.sgml"&gt;</div><div>+&lt;!ENTITY anyarray        SYSTEM "anyarray.sgml"&gt;</div><div> &lt;!ENTITY auth-delay      SYSTEM "auth-delay.sgml"&gt;</div><div> &lt;!ENTITY auto-explain    SYSTEM "auto-explain.sgml"&gt;</div><div> &lt;!ENTITY basic-archive   SYSTEM "basic-archive.sgml"&gt;</div><div>diff --git a/src/test/regress/regression.diffs b/src/test/regress/regression.diffs</div><div>new file mode 100644</div><div>index 00000000000..e69de29bb2d</div><div>diff --git a/src/test/regress/regression.out b/src/test/regress/regression.out</div><div>new file mode 100644</div><div>index 00000000000..9d8d484179c</div><div>--- /dev/null</div><div>+++ b/src/test/regress/regression.out</div><div>@@ -0,0 +1,2 @@</div><div>+# using postmaster on Unix socket, default port</div><div>+# command failed: "/Users/vlad/pgsql/bin/psql" -X -q -c "SET client_min_messages = warning" -c "DROP DATABASE IF EXISTS \"regression\"" "postgres"Bail out!</div><div>diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list</div><div>index cbd9e10fc1d..049485f5c24 100644</div><div>--- a/src/tools/pgindent/typedefs.list</div><div>+++ b/src/tools/pgindent/typedefs.list</div><div>@@ -126,7 +126,13 @@ AnalyzeAttrFetchFunc</div><div> AnalyzeForeignTable_function</div><div> AnlExprData</div><div> AnlIndexData</div><div>+AnyArrayGistKey</div><div>+AnyArrayGistOptions</div><div> AnyArrayType</div><div>+AnyArrayTypeInfo</div><div>+AnyQuery</div><div>+AnyQueryCheck</div><div>+AnyQueryItem</div><div> Append</div><div> AppendPath</div><div> AppendPathInput</div><div>@@ -1744,6 +1750,7 @@ MVNDistinct</div><div> MVNDistinctItem</div><div> ManyTestResource</div><div> ManyTestResourceKind</div><div>+MatchContext</div><div> Material</div><div> MaterialPath</div><div> MaterialState</div><div>@@ -2372,6 +2379,7 @@ PgXmlStrictness</div><div> Pg_abi_values</div><div> Pg_finfo_record</div><div> Pg_magic_struct</div><div>+PickSplitEntry</div><div> PipeProtoChunk</div><div> PipeProtoHeader</div><div> PlaceHolderInfo</div><div>-- </div><div>2.39.5 (Apple Git-154)</div><div> </div></div></div>

^ permalink  raw  reply  [nested|flat] 3+ messages in thread

* Re: [PATCH] Add contrib/anyarray: intarray-style operations and indexes for any array type
  2026-05-18 10:17 [PATCH] Add contrib/anyarray: intarray-style operations and indexes for any array type Влад Медведицков <[email protected]>
@ 2026-05-20 02:24 ` David G. Johnston <[email protected]>
  2026-05-20 15:19   ` Re: [PATCH] Add contrib/anyarray: intarray-style operations and indexes for any array type Влад Медведицков <[email protected]>
  0 siblings, 1 reply; 3+ messages in thread

From: David G. Johnston @ 2026-05-20 02:24 UTC (permalink / raw)
  To: Влад Медведицков <[email protected]>; +Cc: [email protected] <[email protected]>

On Monday, May 18, 2026, Влад Медведицков <[email protected]>
wrote:

> From e796800a32277a29013354344ede221b89e46c27 Mon Sep 17 00:00:00 2001
> From: Vlad Medveditskov <[email protected]>
> Date: Mon, 18 May 2026 12:50:13 +0300
> Subject: [PATCH] Add contrib/anyarray: intarray-style operations and
> indexes
>  for any array type
>
> This new contrib module generalizes contrib/intarray to arrays of any
> element type with a default btree opclass.  It provides:
>
>

You need to attach your patch(es?), not put an email into the body of
another email.

David J.


^ permalink  raw  reply  [nested|flat] 3+ messages in thread

* Re: [PATCH] Add contrib/anyarray: intarray-style operations and indexes for any array type
  2026-05-18 10:17 [PATCH] Add contrib/anyarray: intarray-style operations and indexes for any array type Влад Медведицков <[email protected]>
  2026-05-20 02:24 ` Re: [PATCH] Add contrib/anyarray: intarray-style operations and indexes for any array type David G. Johnston <[email protected]>
@ 2026-05-20 15:19   ` Влад Медведицков <[email protected]>
  0 siblings, 0 replies; 3+ messages in thread

From: Влад Медведицков @ 2026-05-20 15:19 UTC (permalink / raw)
  To: David G. Johnston <[email protected]>; +Cc: [email protected] <[email protected]>


------==--bound.57032.6aac6e78-4ced-434c-8f99-30532fa674c1
Content-Transfer-Encoding: base64
Content-Type: text/html; charset=utf-8

PGRpdj7CoDwvZGl2PjxkaXY+wqA8L2Rpdj48ZGl2Pi0tLS0tLS0tLS0tLS0tLS08L2Rpdj48ZGl2
PtCa0L7QvNGDOiDQktC70LDQtCDQnNC10LTQstC10LTQuNGG0LrQvtCyICh2bGFkbWVkdmVkaXRz
a292QHlhbmRleC5ydSk7PC9kaXY+PGRpdj7QmtC+0L/QuNGPOiBwZ3NxbC1oYWNrZXJzQGxpc3Rz
LnBvc3RncmVzcWwub3JnOzwvZGl2PjxkaXY+0KLQtdC80LA6IFtQQVRDSF0gQWRkIGNvbnRyaWIv
YW55YXJyYXk6IGludGFycmF5LXN0eWxlIG9wZXJhdGlvbnMgYW5kIGluZGV4ZXMgZm9yIGFueSBh
cnJheSB0eXBlOzwvZGl2PjxkaXY+MjAuMDUuMjAyNiwgMDU6MjUsICJEYXZpZCBHLiBKb2huc3Rv
biIgJmx0O2RhdmlkLmcuam9obnN0b25AZ21haWwuY29tJmd0Ozo8L2Rpdj48YmxvY2txdW90ZT5P
biBNb25kYXksIE1heSAxOCwgMjAyNiwg0JLQu9Cw0LQg0JzQtdC00LLQtdC00LjRhtC60L7QsiAm
bHQ7PGEgaHJlZj0ibWFpbHRvOnZsYWRtZWR2ZWRpdHNrb3ZAeWFuZGV4LnJ1IiByZWw9Im5vb3Bl
bmVyIG5vcmVmZXJyZXIiPnZsYWRtZWR2ZWRpdHNrb3ZAeWFuZGV4LnJ1PC9hPiZndDsgd3JvdGU6
PGJsb2NrcXVvdGUgc3R5bGU9ImJvcmRlci1sZWZ0LWNvbG9yOnJnYiggMjA0ICwgMjA0ICwgMjA0
ICk7Ym9yZGVyLWxlZnQtc3R5bGU6c29saWQ7Ym9yZGVyLWxlZnQtd2lkdGg6MXB4O21hcmdpbjow
cHggMHB4IDBweCAwLjhleDtwYWRkaW5nLWxlZnQ6MWV4Ij48ZGl2PkZyb20gZTc5NjgwMGEzMjI3
N2EyOTAxMzM1NDM0NGVkZTIyMWI4OWU0NmMyNyBNb24gU2VwIDE3IDAwOjAwOjAwIDIwMDE8L2Rp
dj48ZGl2PkZyb206IFZsYWQgTWVkdmVkaXRza292ICZsdDs8YSBocmVmPSJtYWlsdG86dmxhZG1l
ZHZlZGl0c2tvdkB5YW5kZXgucnUiIHJlbD0ibm9vcGVuZXIgbm9yZWZlcnJlciIgdGFyZ2V0PSJf
YmxhbmsiPnZsYWRtZWR2ZWRpdHNrb3ZAeWFuZGV4LnJ1PC9hPiZndDs8L2Rpdj48ZGl2PkRhdGU6
IE1vbiwgMTggTWF5IDIwMjYgMTI6NTA6MTMgKzAzMDA8L2Rpdj48ZGl2PlN1YmplY3Q6IFtQQVRD
SF0gQWRkIGNvbnRyaWIvYW55YXJyYXk6IGludGFycmF5LXN0eWxlIG9wZXJhdGlvbnMgYW5kIGlu
ZGV4ZXM8L2Rpdj48ZGl2PsKgZm9yIGFueSBhcnJheSB0eXBlPC9kaXY+PGRpdj7CoDwvZGl2Pjxk
aXY+VGhpcyBuZXcgY29udHJpYiBtb2R1bGUgZ2VuZXJhbGl6ZXMgY29udHJpYi9pbnRhcnJheSB0
byBhcnJheXMgb2YgYW55PC9kaXY+PGRpdj5lbGVtZW50IHR5cGUgd2l0aCBhIGRlZmF1bHQgYnRy
ZWUgb3BjbGFzcy7CoCBJdCBwcm92aWRlczo8L2Rpdj48ZGl2PsKgPC9kaXY+PC9ibG9ja3F1b3Rl
PjxkaXY+wqA8L2Rpdj48ZGl2PllvdSBuZWVkIHRvIGF0dGFjaCB5b3VyIHBhdGNoKGVzPyksIG5v
dCBwdXQgYW4gZW1haWwgaW50byB0aGUgYm9keSBvZiBhbm90aGVyIGVtYWlsLjwvZGl2PjxkaXY+
wqA8L2Rpdj48ZGl2PkRhdmlkIEouPC9kaXY+PGRpdj7CoDwvZGl2PjwvYmxvY2txdW90ZT4=
------==--bound.57032.6aac6e78-4ced-434c-8f99-30532fa674c1
Content-Disposition: attachment;
	filename="0001-Add-contrib-anyarray-intarray-style-operations-and-i.patch"
Content-Transfer-Encoding: base64
Content-Type: application/octet-stream;
	name="0001-Add-contrib-anyarray-intarray-style-operations-and-i.patch"

RnJvbSAwYTZlNzFiYmM0NzBmY2QwYjI5ZTA2ODY1YmY4NWQyYzhhYzE0OGNhIE1vbiBTZXAgMTcg
MDA6MDA6MDAgMjAwMQpGcm9tOiBWbGFkIE1lZHZlZGl0c2tvdiA8dmxhZG1lZHZlZGl0c2tvdkB5
YW5kZXgucnU+CkRhdGU6IE1vbiwgMTggTWF5IDIwMjYgMTI6NTA6MTMgKzAzMDAKU3ViamVjdDog
W1BBVENIXSBBZGQgY29udHJpYi9hbnlhcnJheTogaW50YXJyYXktc3R5bGUgb3BlcmF0aW9ucyBh
bmQgaW5kZXhlcwogZm9yIGFueSBhcnJheSB0eXBlCgpUaGlzIG5ldyBjb250cmliIG1vZHVsZSBn
ZW5lcmFsaXplcyBjb250cmliL2ludGFycmF5IHRvIGFycmF5cyBvZiBhbnkKZWxlbWVudCB0eXBl
IHdpdGggYSBkZWZhdWx0IGJ0cmVlIG9wY2xhc3MuICBJdCBwcm92aWRlczoKCiogU2V0LXN0eWxl
IGhlbHBlcnMgZm9yIGFueWFycmF5IC8gYW55ZWxlbWVudDogYW55YXJyYXlfc29ydAogICh3aXRo
IG9wdGlvbmFsIGFzYy9kZXNjIGRpcmVjdGlvbiksIGFueWFycmF5X3VuaXEsIGFueWFycmF5X2lk
eCwKICBhbnlhcnJheV9zdWJhcnJheSAoMi0gYW5kIDMtYXJnKSwgYW55YXJyYXlfaWNvdW50LAog
IGFueWFycmF5X2ludGVyc2VjdCwgYW55YXJyYXlfdW5pb24sIGFueWFycmF5X3VuaW9uX2VsZW0s
CiAgYW55YXJyYXlfZGlmZmVyZW5jZSwgYW55YXJyYXlfZGlmZmVyZW5jZV9lbGVtLCBwbHVzIHRo
ZQogIGNvcnJlc3BvbmRpbmcgb3BlcmF0b3JzICMsICYsIHwsIC0gb24gYW55YXJyYXkgYW5kIGFu
eWVsZW1lbnQuCgoqIEEgdGV4dHVhbCBib29sZWFuIHF1ZXJ5IHR5cGUgImFueXF1ZXJ5IiBhbmQg
dGhlIG9wZXJhdG9ycwogIGFueWFycmF5IEBAIGFueXF1ZXJ5ICh3aXRoIGNvbW11dGF0b3IgYW55
cXVlcnkgfn4gYW55YXJyYXkpLgogIFRva2VucyBhcmUgc3RvcmVkIGFzIHRleHQgYW5kIHBhcnNl
ZCBsYXppbHkgdGhyb3VnaCB0aGUKICBlbGVtZW50IHR5cGUncyBpbnB1dCBmdW5jdGlvbiBhdCBt
YXRjaCB0aW1lLCBzbyB0aGUgc2FtZQogIHF1ZXJ5IHZhbHVlIGNhbiBiZSB1c2VkIGFnYWluc3Qg
YXJyYXlzIG9mIGRpZmZlcmVudCBlbGVtZW50CiAgdHlwZXMuCgoqIEEgc2lnbmF0dXJlLWJhc2Vk
IHBvbHltb3JwaGljIEdpU1Qgb3BjbGFzcyAiYW55YXJyYXlfZ2lzdF9vcHMiCiAgb24gYW55YXJy
YXkuICBFYWNoIGluZGV4ZWQgYXJyYXkgaXMgaGFzaGVkIGludG8gYSBmaXhlZC1zaXplCiAgYml0
IHZlY3RvcjsgaW50ZXJuYWwgbm9kZXMgc3RvcmUgdGhlIGJpdHdpc2UgdW5pb24gb2YgdGhlaXIK
ICBjaGlsZHJlbiwgd2l0aCBhbiBBTExJU1RSVUUgc2hvcnQtY2lyY3VpdCB3aGVuIGV2ZXJ5IGJp
dCBpcwogIHNldC4gIFNpZ25hdHVyZSBsZW5ndGggaXMgY29uZmlndXJhYmxlIHZpYSB0aGUgc2ln
bGVuCiAgcmVsb3B0aW9uIChkZWZhdWx0IDI1MiBieXRlcykuCgoqIEdJTiBvcGNsYXNzZXMgZm9y
IHRoZSB0aHJlZSBlbGVtZW50IHR5cGVzIG1vc3QgY29tbW9ubHkKICByZXF1ZXN0ZWQgYnkgdXNl
cnM6IGludDhfYW55cXVlcnlfZ2luX29wcywKICB1dWlkX2FueXF1ZXJ5X2dpbl9vcHMgYW5kIHRl
eHRfYW55cXVlcnlfZ2luX29wcy4gIFRoZXkgYXJlCiAgcGVyLWNvbmNyZXRlLXR5cGUgYmVjYXVz
ZSB0aGUgR0lOIEFNIGRvZXMgbm90IHByb3BhZ2F0ZQogIGZuX2V4cHIgaW50byBleHRyYWN0UXVl
cnksIHNvIHRoZSBlbGVtZW50IHR5cGUgbmVlZGVkIHRvCiAgcGFyc2UgYW55cXVlcnkgdG9rZW5z
IGNhbm5vdCBiZSBkaXNjb3ZlcmVkIGR5bmFtaWNhbGx5LgogIFN0cmF0ZWdpZXMgMS00IG1pcnJv
ciB0aGUgYnVpbHQtaW4gYXJyYXlfb3BzOyBzdHJhdGVneSA1CiAgaXMgQEAuCgoqIGRvYy9zcmMv
c2dtbC9hbnlhcnJheS5zZ21sIHdpdGggZGVzY3JpcHRpb25zIG9mIGV2ZXJ5CiAgZnVuY3Rpb24s
IG9wZXJhdG9yIGFuZCBvcGNsYXNzLCBwbHVzIGEgdXNhZ2UgZXhhbXBsZS4KCiogUmVncmVzc2lv
biB0ZXN0IChjb250cmliL2FueWFycmF5L3NxbC9hbnlhcnJheS5zcWwsCiAgZXhwZWN0ZWQvYW55
YXJyYXkub3V0KSBjb3ZlcmluZyBpbnQ4LCB1dWlkIGFuZCB0ZXh0IGlucHV0cywKICB0aGUgZXJy
b3IgcGF0aHMsIGFuZCBhIGNyb3NzLUFNIGNvbnNpc3RlbmN5IGJsb2NrIHRoYXQKICBhc3NlcnRz
IHNlcXNjYW4sIEdpU1QgYW5kIEdJTiByZXR1cm4gdGhlIHNhbWUgcm93IHNldCBmb3IKICBzZXZl
biByZXByZXNlbnRhdGl2ZSBwcmVkaWNhdGVzLgotLS0KIGNvbnRyaWIvTWFrZWZpbGUgICAgICAg
ICAgICAgICAgICAgICAgIHwgICAxICsKIGNvbnRyaWIvYW55YXJyYXkvLmdpdGlnbm9yZSAgICAg
ICAgICAgIHwgICA0ICsKIGNvbnRyaWIvYW55YXJyYXkvTWFrZWZpbGUgICAgICAgICAgICAgIHwg
IDI3ICsKIGNvbnRyaWIvYW55YXJyYXkvYW55YXJyYXktLTEuMC5zcWwgICAgIHwgMzM2ICsrKysr
KysrKysrCiBjb250cmliL2FueWFycmF5L2FueWFycmF5LmMgICAgICAgICAgICB8IDExNiArKysr
CiBjb250cmliL2FueWFycmF5L2FueWFycmF5LmNvbnRyb2wgICAgICB8ICAgNiArCiBjb250cmli
L2FueWFycmF5L2FueWFycmF5LmggICAgICAgICAgICB8IDE4NCArKysrKysKIGNvbnRyaWIvYW55
YXJyYXkvYW55YXJyYXlfYm9vbC5jICAgICAgIHwgNjY0ICsrKysrKysrKysrKysrKysrKysrKysK
IGNvbnRyaWIvYW55YXJyYXkvYW55YXJyYXlfZ2luLmMgICAgICAgIHwgMzc0ICsrKysrKysrKysr
KysKIGNvbnRyaWIvYW55YXJyYXkvYW55YXJyYXlfZ2lzdC5jICAgICAgIHwgNzQyICsrKysrKysr
KysrKysrKysrKysrKysrKysKIGNvbnRyaWIvYW55YXJyYXkvYW55YXJyYXlfb3AuYyAgICAgICAg
IHwgNjEzICsrKysrKysrKysrKysrKysrKysrCiBjb250cmliL2FueWFycmF5L2V4cGVjdGVkL2Fu
eWFycmF5Lm91dCB8IDcyNyArKysrKysrKysrKysrKysrKysrKysrKysKIGNvbnRyaWIvYW55YXJy
YXkvbWVzb24uYnVpbGQgICAgICAgICAgIHwgIDM4ICsrCiBjb250cmliL2FueWFycmF5L3NxbC9h
bnlhcnJheS5zcWwgICAgICB8IDMzMCArKysrKysrKysrKwogY29udHJpYi9tZXNvbi5idWlsZCAg
ICAgICAgICAgICAgICAgICAgfCAgIDEgKwogZG9jL3NyYy9zZ21sL2FueWFycmF5LnNnbWwgICAg
ICAgICAgICAgfCA0ODIgKysrKysrKysrKysrKysrKwogZG9jL3NyYy9zZ21sL2NvbnRyaWIuc2dt
bCAgICAgICAgICAgICAgfCAgIDEgKwogZG9jL3NyYy9zZ21sL2ZpbGVsaXN0LnNnbWwgICAgICAg
ICAgICAgfCAgIDEgKwogc3JjL3Rvb2xzL3BnaW5kZW50L3R5cGVkZWZzLmxpc3QgICAgICAgfCAg
IDggKwogMTkgZmlsZXMgY2hhbmdlZCwgNDY1NSBpbnNlcnRpb25zKCspCiBjcmVhdGUgbW9kZSAx
MDA2NDQgY29udHJpYi9hbnlhcnJheS8uZ2l0aWdub3JlCiBjcmVhdGUgbW9kZSAxMDA2NDQgY29u
dHJpYi9hbnlhcnJheS9NYWtlZmlsZQogY3JlYXRlIG1vZGUgMTAwNjQ0IGNvbnRyaWIvYW55YXJy
YXkvYW55YXJyYXktLTEuMC5zcWwKIGNyZWF0ZSBtb2RlIDEwMDY0NCBjb250cmliL2FueWFycmF5
L2FueWFycmF5LmMKIGNyZWF0ZSBtb2RlIDEwMDY0NCBjb250cmliL2FueWFycmF5L2FueWFycmF5
LmNvbnRyb2wKIGNyZWF0ZSBtb2RlIDEwMDY0NCBjb250cmliL2FueWFycmF5L2FueWFycmF5LmgK
IGNyZWF0ZSBtb2RlIDEwMDY0NCBjb250cmliL2FueWFycmF5L2FueWFycmF5X2Jvb2wuYwogY3Jl
YXRlIG1vZGUgMTAwNjQ0IGNvbnRyaWIvYW55YXJyYXkvYW55YXJyYXlfZ2luLmMKIGNyZWF0ZSBt
b2RlIDEwMDY0NCBjb250cmliL2FueWFycmF5L2FueWFycmF5X2dpc3QuYwogY3JlYXRlIG1vZGUg
MTAwNjQ0IGNvbnRyaWIvYW55YXJyYXkvYW55YXJyYXlfb3AuYwogY3JlYXRlIG1vZGUgMTAwNjQ0
IGNvbnRyaWIvYW55YXJyYXkvZXhwZWN0ZWQvYW55YXJyYXkub3V0CiBjcmVhdGUgbW9kZSAxMDA2
NDQgY29udHJpYi9hbnlhcnJheS9tZXNvbi5idWlsZAogY3JlYXRlIG1vZGUgMTAwNjQ0IGNvbnRy
aWIvYW55YXJyYXkvc3FsL2FueWFycmF5LnNxbAogY3JlYXRlIG1vZGUgMTAwNjQ0IGRvYy9zcmMv
c2dtbC9hbnlhcnJheS5zZ21sCgpkaWZmIC0tZ2l0IGEvY29udHJpYi9NYWtlZmlsZSBiL2NvbnRy
aWIvTWFrZWZpbGUKaW5kZXggN2Q5MWZlNzdkYjMuLmI5NTg2Y2IzYTZiIDEwMDY0NAotLS0gYS9j
b250cmliL01ha2VmaWxlCisrKyBiL2NvbnRyaWIvTWFrZWZpbGUKQEAgLTYsNiArNiw3IEBAIGlu
Y2x1ZGUgJCh0b3BfYnVpbGRkaXIpL3NyYy9NYWtlZmlsZS5nbG9iYWwKIAogU1VCRElSUyA9IFwK
IAkJYW1jaGVjawkJXAorCQlhbnlhcnJheQlcCiAJCWF1dGhfZGVsYXkJXAogCQlhdXRvX2V4cGxh
aW4JXAogCQliYXNpY19hcmNoaXZlCVwKZGlmZiAtLWdpdCBhL2NvbnRyaWIvYW55YXJyYXkvLmdp
dGlnbm9yZSBiL2NvbnRyaWIvYW55YXJyYXkvLmdpdGlnbm9yZQpuZXcgZmlsZSBtb2RlIDEwMDY0
NAppbmRleCAwMDAwMDAwMDAwMC4uNWRjYjNmZjk3MjMKLS0tIC9kZXYvbnVsbAorKysgYi9jb250
cmliL2FueWFycmF5Ly5naXRpZ25vcmUKQEAgLTAsMCArMSw0IEBACisjIEdlbmVyYXRlZCBzdWJk
aXJlY3RvcmllcworL2xvZy8KKy9yZXN1bHRzLworL3RtcF9jaGVjay8KZGlmZiAtLWdpdCBhL2Nv
bnRyaWIvYW55YXJyYXkvTWFrZWZpbGUgYi9jb250cmliL2FueWFycmF5L01ha2VmaWxlCm5ldyBm
aWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAwMDAwLi5kNmViOWFlMTBhZAotLS0gL2Rldi9u
dWxsCisrKyBiL2NvbnRyaWIvYW55YXJyYXkvTWFrZWZpbGUKQEAgLTAsMCArMSwyNyBAQAorIyBj
b250cmliL2FueWFycmF5L01ha2VmaWxlCisKK01PRFVMRV9iaWcgPSBhbnlhcnJheQorT0JKUyA9
IFwKKwkkKFdJTjMyUkVTKSBcCisJYW55YXJyYXkubyBcCisJYW55YXJyYXlfYm9vbC5vIFwKKwlh
bnlhcnJheV9naW4ubyBcCisJYW55YXJyYXlfZ2lzdC5vIFwKKwlhbnlhcnJheV9vcC5vCisKK0VY
VEVOU0lPTiA9IGFueWFycmF5CitEQVRBID0gYW55YXJyYXktLTEuMC5zcWwKK1BHRklMRURFU0Mg
PSAiYW55YXJyYXkgLSBvcGVyYXRpb25zIGFuZCBpbmRleGVzIGZvciBhcnJheXMgb2YgYW55IHR5
cGUiCisKK1JFR1JFU1MgPSBhbnlhcnJheQorCitpZmRlZiBVU0VfUEdYUworUEdfQ09ORklHID0g
cGdfY29uZmlnCitQR1hTIDo9ICQoc2hlbGwgJChQR19DT05GSUcpIC0tcGd4cykKK2luY2x1ZGUg
JChQR1hTKQorZWxzZQorc3ViZGlyID0gY29udHJpYi9hbnlhcnJheQordG9wX2J1aWxkZGlyID0g
Li4vLi4KK2luY2x1ZGUgJCh0b3BfYnVpbGRkaXIpL3NyYy9NYWtlZmlsZS5nbG9iYWwKK2luY2x1
ZGUgJCh0b3Bfc3JjZGlyKS9jb250cmliL2NvbnRyaWItZ2xvYmFsLm1rCitlbmRpZgpkaWZmIC0t
Z2l0IGEvY29udHJpYi9hbnlhcnJheS9hbnlhcnJheS0tMS4wLnNxbCBiL2NvbnRyaWIvYW55YXJy
YXkvYW55YXJyYXktLTEuMC5zcWwKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAw
MDAuLjg0YmNmZjM0YjViCi0tLSAvZGV2L251bGwKKysrIGIvY29udHJpYi9hbnlhcnJheS9hbnlh
cnJheS0tMS4wLnNxbApAQCAtMCwwICsxLDMzNiBAQAorLyogY29udHJpYi9hbnlhcnJheS9hbnlh
cnJheS0tMS4wLnNxbCAqLworCistLSBjb21wbGFpbiBpZiBzY3JpcHQgaXMgc291cmNlZCBpbiBw
c3FsLCByYXRoZXIgdGhhbiB2aWEgQ1JFQVRFIEVYVEVOU0lPTgorXGVjaG8gVXNlICJDUkVBVEUg
RVhURU5TSU9OIGFueWFycmF5IiB0byBsb2FkIHRoaXMgZmlsZS4gXHF1aXQKKworLS0KKy0tIFNl
dC1zdHlsZSBvcGVyYXRpb25zIGZvciBhcnJheXMgb2YgYW55IGJ0cmVlLW9yZGVyYWJsZSBlbGVt
ZW50IHR5cGUuCistLQorCitDUkVBVEUgRlVOQ1RJT04gYW55YXJyYXlfc29ydChhbnlhcnJheSkK
K1JFVFVSTlMgYW55YXJyYXkKK0FTICdNT0RVTEVfUEFUSE5BTUUnLCAnYW55YXJyYXlfc29ydCcK
K0xBTkdVQUdFIEMgU1RSSUNUIElNTVVUQUJMRSBQQVJBTExFTCBTQUZFOworCitDUkVBVEUgRlVO
Q1RJT04gYW55YXJyYXlfc29ydChhbnlhcnJheSwgdGV4dCkKK1JFVFVSTlMgYW55YXJyYXkKK0FT
ICdNT0RVTEVfUEFUSE5BTUUnLCAnYW55YXJyYXlfc29ydF9kaXInCitMQU5HVUFHRSBDIFNUUklD
VCBJTU1VVEFCTEUgUEFSQUxMRUwgU0FGRTsKKworQ1JFQVRFIEZVTkNUSU9OIGFueWFycmF5X3Vu
aXEoYW55YXJyYXkpCitSRVRVUk5TIGFueWFycmF5CitBUyAnTU9EVUxFX1BBVEhOQU1FJywgJ2Fu
eWFycmF5X3VuaXEnCitMQU5HVUFHRSBDIFNUUklDVCBJTU1VVEFCTEUgUEFSQUxMRUwgU0FGRTsK
KworQ1JFQVRFIEZVTkNUSU9OIGFueWFycmF5X2lkeChhbnlhcnJheSwgYW55ZWxlbWVudCkKK1JF
VFVSTlMgaW50NAorQVMgJ01PRFVMRV9QQVRITkFNRScsICdhbnlhcnJheV9pZHgnCitMQU5HVUFH
RSBDIFNUUklDVCBJTU1VVEFCTEUgUEFSQUxMRUwgU0FGRTsKKworQ1JFQVRFIEZVTkNUSU9OIGFu
eWFycmF5X3N1YmFycmF5KGFueWFycmF5LCBpbnQ0LCBpbnQ0KQorUkVUVVJOUyBhbnlhcnJheQor
QVMgJ01PRFVMRV9QQVRITkFNRScsICdhbnlhcnJheV9zdWJhcnJheScKK0xBTkdVQUdFIEMgU1RS
SUNUIElNTVVUQUJMRSBQQVJBTExFTCBTQUZFOworCitDUkVBVEUgRlVOQ1RJT04gYW55YXJyYXlf
c3ViYXJyYXkoYW55YXJyYXksIGludDQpCitSRVRVUk5TIGFueWFycmF5CitBUyAnTU9EVUxFX1BB
VEhOQU1FJywgJ2FueWFycmF5X3N1YmFycmF5X3RvX2VuZCcKK0xBTkdVQUdFIEMgU1RSSUNUIElN
TVVUQUJMRSBQQVJBTExFTCBTQUZFOworCitDUkVBVEUgRlVOQ1RJT04gYW55YXJyYXlfaWNvdW50
KGFueWFycmF5KQorUkVUVVJOUyBpbnQ0CitBUyAnTU9EVUxFX1BBVEhOQU1FJywgJ2FueWFycmF5
X2ljb3VudCcKK0xBTkdVQUdFIEMgU1RSSUNUIElNTVVUQUJMRSBQQVJBTExFTCBTQUZFOworCitD
UkVBVEUgRlVOQ1RJT04gYW55YXJyYXlfaW50ZXJzZWN0KGFueWFycmF5LCBhbnlhcnJheSkKK1JF
VFVSTlMgYW55YXJyYXkKK0FTICdNT0RVTEVfUEFUSE5BTUUnLCAnYW55YXJyYXlfaW50ZXJzZWN0
JworTEFOR1VBR0UgQyBTVFJJQ1QgSU1NVVRBQkxFIFBBUkFMTEVMIFNBRkU7CisKK0NSRUFURSBG
VU5DVElPTiBhbnlhcnJheV91bmlvbihhbnlhcnJheSwgYW55YXJyYXkpCitSRVRVUk5TIGFueWFy
cmF5CitBUyAnTU9EVUxFX1BBVEhOQU1FJywgJ2FueWFycmF5X3VuaW9uJworTEFOR1VBR0UgQyBT
VFJJQ1QgSU1NVVRBQkxFIFBBUkFMTEVMIFNBRkU7CisKK0NSRUFURSBGVU5DVElPTiBhbnlhcnJh
eV91bmlvbl9lbGVtKGFueWFycmF5LCBhbnllbGVtZW50KQorUkVUVVJOUyBhbnlhcnJheQorQVMg
J01PRFVMRV9QQVRITkFNRScsICdhbnlhcnJheV91bmlvbl9lbGVtJworTEFOR1VBR0UgQyBTVFJJ
Q1QgSU1NVVRBQkxFIFBBUkFMTEVMIFNBRkU7CisKK0NSRUFURSBGVU5DVElPTiBhbnlhcnJheV9k
aWZmZXJlbmNlKGFueWFycmF5LCBhbnlhcnJheSkKK1JFVFVSTlMgYW55YXJyYXkKK0FTICdNT0RV
TEVfUEFUSE5BTUUnLCAnYW55YXJyYXlfZGlmZmVyZW5jZScKK0xBTkdVQUdFIEMgU1RSSUNUIElN
TVVUQUJMRSBQQVJBTExFTCBTQUZFOworCitDUkVBVEUgRlVOQ1RJT04gYW55YXJyYXlfZGlmZmVy
ZW5jZV9lbGVtKGFueWFycmF5LCBhbnllbGVtZW50KQorUkVUVVJOUyBhbnlhcnJheQorQVMgJ01P
RFVMRV9QQVRITkFNRScsICdhbnlhcnJheV9kaWZmZXJlbmNlX2VsZW0nCitMQU5HVUFHRSBDIFNU
UklDVCBJTU1VVEFCTEUgUEFSQUxMRUwgU0FGRTsKKworLS0KKy0tIE9wZXJhdG9ycworLS0KKwor
LS0gVW5hcnkgcHJlZml4ICMgOiBjYXJkaW5hbGl0eSAobnVtYmVyIG9mIGVsZW1lbnRzKQorQ1JF
QVRFIE9QRVJBVE9SICMgKAorCVJJR0hUQVJHID0gYW55YXJyYXksCisJUFJPQ0VEVVJFID0gYW55
YXJyYXlfaWNvdW50CispOworCistLSBhcnJheSAjIGVsZW1lbnQgOiAxLWJhc2VkIGluZGV4IG9m
IGVsZW1lbnQsIG9yIDAgaWYgbm90IGZvdW5kCitDUkVBVEUgT1BFUkFUT1IgIyAoCisJTEVGVEFS
RyA9IGFueWFycmF5LAorCVJJR0hUQVJHID0gYW55ZWxlbWVudCwKKwlQUk9DRURVUkUgPSBhbnlh
cnJheV9pZHgKKyk7CisKKy0tIFNldCBpbnRlcnNlY3Rpb24KK0NSRUFURSBPUEVSQVRPUiAmICgK
KwlMRUZUQVJHID0gYW55YXJyYXksCisJUklHSFRBUkcgPSBhbnlhcnJheSwKKwlDT01NVVRBVE9S
ID0gJiwKKwlQUk9DRURVUkUgPSBhbnlhcnJheV9pbnRlcnNlY3QKKyk7CisKKy0tIFNldCB1bmlv
biAoYXJyYXkgfCBhcnJheSkKK0NSRUFURSBPUEVSQVRPUiB8ICgKKwlMRUZUQVJHID0gYW55YXJy
YXksCisJUklHSFRBUkcgPSBhbnlhcnJheSwKKwlDT01NVVRBVE9SID0gfCwKKwlQUk9DRURVUkUg
PSBhbnlhcnJheV91bmlvbgorKTsKKworLS0gQXBwZW5kIGVsZW1lbnQgKGFycmF5IHwgZWxlbWVu
dCkKK0NSRUFURSBPUEVSQVRPUiB8ICgKKwlMRUZUQVJHID0gYW55YXJyYXksCisJUklHSFRBUkcg
PSBhbnllbGVtZW50LAorCVBST0NFRFVSRSA9IGFueWFycmF5X3VuaW9uX2VsZW0KKyk7CisKKy0t
IFNldCBkaWZmZXJlbmNlIChhcnJheSAtIGFycmF5KQorQ1JFQVRFIE9QRVJBVE9SIC0gKAorCUxF
RlRBUkcgPSBhbnlhcnJheSwKKwlSSUdIVEFSRyA9IGFueWFycmF5LAorCVBST0NFRFVSRSA9IGFu
eWFycmF5X2RpZmZlcmVuY2UKKyk7CisKKy0tIFJlbW92ZSBhbGwgb2NjdXJyZW5jZXMgb2YgZWxl
bWVudCAoYXJyYXkgLSBlbGVtZW50KQorQ1JFQVRFIE9QRVJBVE9SIC0gKAorCUxFRlRBUkcgPSBh
bnlhcnJheSwKKwlSSUdIVEFSRyA9IGFueWVsZW1lbnQsCisJUFJPQ0VEVVJFID0gYW55YXJyYXlf
ZGlmZmVyZW5jZV9lbGVtCispOworCistLQorLS0gQm9vbGVhbiBxdWVyeSB0eXBlCistLQorCitD
UkVBVEUgRlVOQ1RJT04gYW55cXVlcnlfaW4oY3N0cmluZykKK1JFVFVSTlMgYW55cXVlcnkKK0FT
ICdNT0RVTEVfUEFUSE5BTUUnLCAnYW55cXVlcnlfaW4nCitMQU5HVUFHRSBDIFNUUklDVCBJTU1V
VEFCTEUgUEFSQUxMRUwgU0FGRTsKKworQ1JFQVRFIEZVTkNUSU9OIGFueXF1ZXJ5X291dChhbnlx
dWVyeSkKK1JFVFVSTlMgY3N0cmluZworQVMgJ01PRFVMRV9QQVRITkFNRScsICdhbnlxdWVyeV9v
dXQnCitMQU5HVUFHRSBDIFNUUklDVCBJTU1VVEFCTEUgUEFSQUxMRUwgU0FGRTsKKworQ1JFQVRF
IFRZUEUgYW55cXVlcnkgKAorCUlOVEVSTkFMTEVOR1RIID0gLTEsCisJSU5QVVQgPSBhbnlxdWVy
eV9pbiwKKwlPVVRQVVQgPSBhbnlxdWVyeV9vdXQsCisJU1RPUkFHRSA9IGV4dGVuZGVkCispOwor
CitDUkVBVEUgRlVOQ1RJT04gYW55cXVlcnlfcXVlcnl0cmVlKGFueXF1ZXJ5KQorUkVUVVJOUyB0
ZXh0CitBUyAnTU9EVUxFX1BBVEhOQU1FJywgJ2FueXF1ZXJ5X3F1ZXJ5dHJlZScKK0xBTkdVQUdF
IEMgU1RSSUNUIElNTVVUQUJMRSBQQVJBTExFTCBTQUZFOworCitDUkVBVEUgRlVOQ1RJT04gYW55
YXJyYXlfYm9vbG9wKGFueWFycmF5LCBhbnlxdWVyeSkKK1JFVFVSTlMgYm9vbAorQVMgJ01PRFVM
RV9QQVRITkFNRScsICdhbnlhcnJheV9ib29sb3AnCitMQU5HVUFHRSBDIFNUUklDVCBJTU1VVEFC
TEUgUEFSQUxMRUwgU0FGRTsKKworQ1JFQVRFIEZVTkNUSU9OIGFueXF1ZXJ5X2Jvb2xvcF9yZXYo
YW55cXVlcnksIGFueWFycmF5KQorUkVUVVJOUyBib29sCitBUyAnTU9EVUxFX1BBVEhOQU1FJywg
J2FueXF1ZXJ5X2Jvb2xvcF9yZXYnCitMQU5HVUFHRSBDIFNUUklDVCBJTU1VVEFCTEUgUEFSQUxM
RUwgU0FGRTsKKworQ1JFQVRFIE9QRVJBVE9SIEBAICgKKwlMRUZUQVJHID0gYW55YXJyYXksCisJ
UklHSFRBUkcgPSBhbnlxdWVyeSwKKwlQUk9DRURVUkUgPSBhbnlhcnJheV9ib29sb3AsCisJQ09N
TVVUQVRPUiA9ICd+ficsCisJUkVTVFJJQ1QgPSBjb250c2VsLAorCUpPSU4gPSBjb250am9pbnNl
bAorKTsKKworQ1JFQVRFIE9QRVJBVE9SIH5+ICgKKwlMRUZUQVJHID0gYW55cXVlcnksCisJUklH
SFRBUkcgPSBhbnlhcnJheSwKKwlQUk9DRURVUkUgPSBhbnlxdWVyeV9ib29sb3BfcmV2LAorCUNP
TU1VVEFUT1IgPSAnQEAnLAorCVJFU1RSSUNUID0gY29udHNlbCwKKwlKT0lOID0gY29udGpvaW5z
ZWwKKyk7CisKKy0tCistLSBHaVNUIG9wY2xhc3MgKHNpZ25hdHVyZS1iYXNlZCkKKy0tCisKK0NS
RUFURSBGVU5DVElPTiBhbnlhcnJheV9naXN0X2tleV9pbihjc3RyaW5nKQorUkVUVVJOUyBhbnlh
cnJheV9naXN0X2tleQorQVMgJ01PRFVMRV9QQVRITkFNRScsICdhbnlhcnJheV9naXN0X2tleV9p
bicKK0xBTkdVQUdFIEMgU1RSSUNUIElNTVVUQUJMRSBQQVJBTExFTCBTQUZFOworCitDUkVBVEUg
RlVOQ1RJT04gYW55YXJyYXlfZ2lzdF9rZXlfb3V0KGFueWFycmF5X2dpc3Rfa2V5KQorUkVUVVJO
UyBjc3RyaW5nCitBUyAnTU9EVUxFX1BBVEhOQU1FJywgJ2FueWFycmF5X2dpc3Rfa2V5X291dCcK
K0xBTkdVQUdFIEMgU1RSSUNUIElNTVVUQUJMRSBQQVJBTExFTCBTQUZFOworCitDUkVBVEUgVFlQ
RSBhbnlhcnJheV9naXN0X2tleSAoCisJSU5URVJOQUxMRU5HVEggPSAtMSwKKwlJTlBVVCA9IGFu
eWFycmF5X2dpc3Rfa2V5X2luLAorCU9VVFBVVCA9IGFueWFycmF5X2dpc3Rfa2V5X291dAorKTsK
KworQ1JFQVRFIEZVTkNUSU9OIGFueWFycmF5X2dpc3RfY29uc2lzdGVudChpbnRlcm5hbCwgYW55
YXJyYXksIHNtYWxsaW50LCBvaWQsIGludGVybmFsKQorUkVUVVJOUyBib29sCitBUyAnTU9EVUxF
X1BBVEhOQU1FJywgJ2FueWFycmF5X2dpc3RfY29uc2lzdGVudCcKK0xBTkdVQUdFIEMgSU1NVVRB
QkxFIFBBUkFMTEVMIFNBRkU7CisKK0NSRUFURSBGVU5DVElPTiBhbnlhcnJheV9naXN0X2NvbXBy
ZXNzKGludGVybmFsKQorUkVUVVJOUyBpbnRlcm5hbAorQVMgJ01PRFVMRV9QQVRITkFNRScsICdh
bnlhcnJheV9naXN0X2NvbXByZXNzJworTEFOR1VBR0UgQyBJTU1VVEFCTEUgU1RSSUNUIFBBUkFM
TEVMIFNBRkU7CisKK0NSRUFURSBGVU5DVElPTiBhbnlhcnJheV9naXN0X2RlY29tcHJlc3MoaW50
ZXJuYWwpCitSRVRVUk5TIGludGVybmFsCitBUyAnTU9EVUxFX1BBVEhOQU1FJywgJ2FueWFycmF5
X2dpc3RfZGVjb21wcmVzcycKK0xBTkdVQUdFIEMgSU1NVVRBQkxFIFNUUklDVCBQQVJBTExFTCBT
QUZFOworCitDUkVBVEUgRlVOQ1RJT04gYW55YXJyYXlfZ2lzdF91bmlvbihpbnRlcm5hbCwgaW50
ZXJuYWwpCitSRVRVUk5TIGFueWFycmF5X2dpc3Rfa2V5CitBUyAnTU9EVUxFX1BBVEhOQU1FJywg
J2FueWFycmF5X2dpc3RfdW5pb24nCitMQU5HVUFHRSBDIElNTVVUQUJMRSBTVFJJQ1QgUEFSQUxM
RUwgU0FGRTsKKworQ1JFQVRFIEZVTkNUSU9OIGFueWFycmF5X2dpc3Rfc2FtZShhbnlhcnJheV9n
aXN0X2tleSwgYW55YXJyYXlfZ2lzdF9rZXksIGludGVybmFsKQorUkVUVVJOUyBpbnRlcm5hbAor
QVMgJ01PRFVMRV9QQVRITkFNRScsICdhbnlhcnJheV9naXN0X3NhbWUnCitMQU5HVUFHRSBDIElN
TVVUQUJMRSBTVFJJQ1QgUEFSQUxMRUwgU0FGRTsKKworQ1JFQVRFIEZVTkNUSU9OIGFueWFycmF5
X2dpc3RfcGVuYWx0eShpbnRlcm5hbCwgaW50ZXJuYWwsIGludGVybmFsKQorUkVUVVJOUyBpbnRl
cm5hbAorQVMgJ01PRFVMRV9QQVRITkFNRScsICdhbnlhcnJheV9naXN0X3BlbmFsdHknCitMQU5H
VUFHRSBDIElNTVVUQUJMRSBTVFJJQ1QgUEFSQUxMRUwgU0FGRTsKKworQ1JFQVRFIEZVTkNUSU9O
IGFueWFycmF5X2dpc3RfcGlja3NwbGl0KGludGVybmFsLCBpbnRlcm5hbCkKK1JFVFVSTlMgaW50
ZXJuYWwKK0FTICdNT0RVTEVfUEFUSE5BTUUnLCAnYW55YXJyYXlfZ2lzdF9waWNrc3BsaXQnCitM
QU5HVUFHRSBDIElNTVVUQUJMRSBTVFJJQ1QgUEFSQUxMRUwgU0FGRTsKKworQ1JFQVRFIEZVTkNU
SU9OIGFueWFycmF5X2dpc3Rfb3B0aW9ucyhpbnRlcm5hbCkKK1JFVFVSTlMgdm9pZAorQVMgJ01P
RFVMRV9QQVRITkFNRScsICdhbnlhcnJheV9naXN0X29wdGlvbnMnCitMQU5HVUFHRSBDIElNTVVU
QUJMRSBTVFJJQ1QgUEFSQUxMRUwgU0FGRTsKKworQ1JFQVRFIE9QRVJBVE9SIENMQVNTIGFueWFy
cmF5X2dpc3Rfb3BzCitGT1IgVFlQRSBhbnlhcnJheSBVU0lORyBnaXN0CitBUworCU9QRVJBVE9S
CTMJJiYsCisJT1BFUkFUT1IJNwlAPiwKKwlPUEVSQVRPUgk4CTxALAorCU9QRVJBVE9SCTE4CT0s
CisJT1BFUkFUT1IJMjAJQEAgKGFueWFycmF5LCBhbnlxdWVyeSksCisJRlVOQ1RJT04JMQlhbnlh
cnJheV9naXN0X2NvbnNpc3RlbnQoaW50ZXJuYWwsIGFueWFycmF5LCBzbWFsbGludCwgb2lkLCBp
bnRlcm5hbCksCisJRlVOQ1RJT04JMglhbnlhcnJheV9naXN0X3VuaW9uKGludGVybmFsLCBpbnRl
cm5hbCksCisJRlVOQ1RJT04JMwlhbnlhcnJheV9naXN0X2NvbXByZXNzKGludGVybmFsKSwKKwlG
VU5DVElPTgk0CWFueWFycmF5X2dpc3RfZGVjb21wcmVzcyhpbnRlcm5hbCksCisJRlVOQ1RJT04J
NQlhbnlhcnJheV9naXN0X3BlbmFsdHkoaW50ZXJuYWwsIGludGVybmFsLCBpbnRlcm5hbCksCisJ
RlVOQ1RJT04JNglhbnlhcnJheV9naXN0X3BpY2tzcGxpdChpbnRlcm5hbCwgaW50ZXJuYWwpLAor
CUZVTkNUSU9OCTcJYW55YXJyYXlfZ2lzdF9zYW1lKGFueWFycmF5X2dpc3Rfa2V5LCBhbnlhcnJh
eV9naXN0X2tleSwgaW50ZXJuYWwpLAorCUZVTkNUSU9OCTEwCWFueWFycmF5X2dpc3Rfb3B0aW9u
cyhpbnRlcm5hbCksCisJU1RPUkFHRQkJYW55YXJyYXlfZ2lzdF9rZXk7CisKKy0tCistLSBHSU4g
b3BjbGFzc2VzIChwZXIgY29uY3JldGUgZWxlbWVudCB0eXBlLCBzdXBwb3J0aW5nIHN0YW5kYXJk
IG9wcyArIEBAKQorLS0KKworQ1JFQVRFIEZVTkNUSU9OIGFueWFycmF5X2dpbl9leHRyYWN0X3F1
ZXJ5X2ludDgoCisJaW50OFtdLCBpbnRlcm5hbCwgc21hbGxpbnQsIGludGVybmFsLCBpbnRlcm5h
bCwgaW50ZXJuYWwsIGludGVybmFsKQorUkVUVVJOUyBpbnRlcm5hbAorQVMgJ01PRFVMRV9QQVRI
TkFNRScsICdhbnlhcnJheV9naW5fZXh0cmFjdF9xdWVyeV9pbnQ4JworTEFOR1VBR0UgQyBJTU1V
VEFCTEUgU1RSSUNUIFBBUkFMTEVMIFNBRkU7CisKK0NSRUFURSBGVU5DVElPTiBhbnlhcnJheV9n
aW5fY29uc2lzdGVudF9pbnQ4KAorCWludGVybmFsLCBzbWFsbGludCwgaW50OFtdLCBpbnRlZ2Vy
LCBpbnRlcm5hbCwgaW50ZXJuYWwsIGludGVybmFsLCBpbnRlcm5hbCkKK1JFVFVSTlMgYm9vbAor
QVMgJ01PRFVMRV9QQVRITkFNRScsICdhbnlhcnJheV9naW5fY29uc2lzdGVudF9pbnQ4JworTEFO
R1VBR0UgQyBJTU1VVEFCTEUgU1RSSUNUIFBBUkFMTEVMIFNBRkU7CisKK0NSRUFURSBPUEVSQVRP
UiBDTEFTUyBpbnQ4X2FueXF1ZXJ5X2dpbl9vcHMKK0ZPUiBUWVBFIGludDhbXSBVU0lORyBnaW4K
K0FTCisJT1BFUkFUT1IJMQkmJiAoYW55YXJyYXksIGFueWFycmF5KSwKKwlPUEVSQVRPUgkyCUA+
IChhbnlhcnJheSwgYW55YXJyYXkpLAorCU9QRVJBVE9SCTMJPEAgKGFueWFycmF5LCBhbnlhcnJh
eSksCisJT1BFUkFUT1IJNAk9IChhbnlhcnJheSwgYW55YXJyYXkpLAorCU9QRVJBVE9SCTUJQEAg
KGFueWFycmF5LCBhbnlxdWVyeSksCisJRlVOQ1RJT04JMQlidGludDhjbXAoaW50OCwgaW50OCks
CisJRlVOQ1RJT04JMglnaW5hcnJheWV4dHJhY3QoYW55YXJyYXksIGludGVybmFsLCBpbnRlcm5h
bCksCisJRlVOQ1RJT04JMwlhbnlhcnJheV9naW5fZXh0cmFjdF9xdWVyeV9pbnQ4KGludDhbXSwg
aW50ZXJuYWwsIHNtYWxsaW50LCBpbnRlcm5hbCwgaW50ZXJuYWwsIGludGVybmFsLCBpbnRlcm5h
bCksCisJRlVOQ1RJT04JNAlhbnlhcnJheV9naW5fY29uc2lzdGVudF9pbnQ4KGludGVybmFsLCBz
bWFsbGludCwgaW50OFtdLCBpbnRlZ2VyLCBpbnRlcm5hbCwgaW50ZXJuYWwsIGludGVybmFsLCBp
bnRlcm5hbCksCisJU1RPUkFHRQkJaW50ODsKKworQ1JFQVRFIEZVTkNUSU9OIGFueWFycmF5X2dp
bl9leHRyYWN0X3F1ZXJ5X3V1aWQoCisJdXVpZFtdLCBpbnRlcm5hbCwgc21hbGxpbnQsIGludGVy
bmFsLCBpbnRlcm5hbCwgaW50ZXJuYWwsIGludGVybmFsKQorUkVUVVJOUyBpbnRlcm5hbAorQVMg
J01PRFVMRV9QQVRITkFNRScsICdhbnlhcnJheV9naW5fZXh0cmFjdF9xdWVyeV91dWlkJworTEFO
R1VBR0UgQyBJTU1VVEFCTEUgU1RSSUNUIFBBUkFMTEVMIFNBRkU7CisKK0NSRUFURSBGVU5DVElP
TiBhbnlhcnJheV9naW5fY29uc2lzdGVudF91dWlkKAorCWludGVybmFsLCBzbWFsbGludCwgdXVp
ZFtdLCBpbnRlZ2VyLCBpbnRlcm5hbCwgaW50ZXJuYWwsIGludGVybmFsLCBpbnRlcm5hbCkKK1JF
VFVSTlMgYm9vbAorQVMgJ01PRFVMRV9QQVRITkFNRScsICdhbnlhcnJheV9naW5fY29uc2lzdGVu
dF91dWlkJworTEFOR1VBR0UgQyBJTU1VVEFCTEUgU1RSSUNUIFBBUkFMTEVMIFNBRkU7CisKK0NS
RUFURSBPUEVSQVRPUiBDTEFTUyB1dWlkX2FueXF1ZXJ5X2dpbl9vcHMKK0ZPUiBUWVBFIHV1aWRb
XSBVU0lORyBnaW4KK0FTCisJT1BFUkFUT1IJMQkmJiAoYW55YXJyYXksIGFueWFycmF5KSwKKwlP
UEVSQVRPUgkyCUA+IChhbnlhcnJheSwgYW55YXJyYXkpLAorCU9QRVJBVE9SCTMJPEAgKGFueWFy
cmF5LCBhbnlhcnJheSksCisJT1BFUkFUT1IJNAk9IChhbnlhcnJheSwgYW55YXJyYXkpLAorCU9Q
RVJBVE9SCTUJQEAgKGFueWFycmF5LCBhbnlxdWVyeSksCisJRlVOQ1RJT04JMQl1dWlkX2NtcCh1
dWlkLCB1dWlkKSwKKwlGVU5DVElPTgkyCWdpbmFycmF5ZXh0cmFjdChhbnlhcnJheSwgaW50ZXJu
YWwsIGludGVybmFsKSwKKwlGVU5DVElPTgkzCWFueWFycmF5X2dpbl9leHRyYWN0X3F1ZXJ5X3V1
aWQodXVpZFtdLCBpbnRlcm5hbCwgc21hbGxpbnQsIGludGVybmFsLCBpbnRlcm5hbCwgaW50ZXJu
YWwsIGludGVybmFsKSwKKwlGVU5DVElPTgk0CWFueWFycmF5X2dpbl9jb25zaXN0ZW50X3V1aWQo
aW50ZXJuYWwsIHNtYWxsaW50LCB1dWlkW10sIGludGVnZXIsIGludGVybmFsLCBpbnRlcm5hbCwg
aW50ZXJuYWwsIGludGVybmFsKSwKKwlTVE9SQUdFCQl1dWlkOworCitDUkVBVEUgRlVOQ1RJT04g
YW55YXJyYXlfZ2luX2V4dHJhY3RfcXVlcnlfdGV4dCgKKwl0ZXh0W10sIGludGVybmFsLCBzbWFs
bGludCwgaW50ZXJuYWwsIGludGVybmFsLCBpbnRlcm5hbCwgaW50ZXJuYWwpCitSRVRVUk5TIGlu
dGVybmFsCitBUyAnTU9EVUxFX1BBVEhOQU1FJywgJ2FueWFycmF5X2dpbl9leHRyYWN0X3F1ZXJ5
X3RleHQnCitMQU5HVUFHRSBDIElNTVVUQUJMRSBTVFJJQ1QgUEFSQUxMRUwgU0FGRTsKKworQ1JF
QVRFIEZVTkNUSU9OIGFueWFycmF5X2dpbl9jb25zaXN0ZW50X3RleHQoCisJaW50ZXJuYWwsIHNt
YWxsaW50LCB0ZXh0W10sIGludGVnZXIsIGludGVybmFsLCBpbnRlcm5hbCwgaW50ZXJuYWwsIGlu
dGVybmFsKQorUkVUVVJOUyBib29sCitBUyAnTU9EVUxFX1BBVEhOQU1FJywgJ2FueWFycmF5X2dp
bl9jb25zaXN0ZW50X3RleHQnCitMQU5HVUFHRSBDIElNTVVUQUJMRSBTVFJJQ1QgUEFSQUxMRUwg
U0FGRTsKKworQ1JFQVRFIE9QRVJBVE9SIENMQVNTIHRleHRfYW55cXVlcnlfZ2luX29wcworRk9S
IFRZUEUgdGV4dFtdIFVTSU5HIGdpbgorQVMKKwlPUEVSQVRPUgkxCSYmIChhbnlhcnJheSwgYW55
YXJyYXkpLAorCU9QRVJBVE9SCTIJQD4gKGFueWFycmF5LCBhbnlhcnJheSksCisJT1BFUkFUT1IJ
Mwk8QCAoYW55YXJyYXksIGFueWFycmF5KSwKKwlPUEVSQVRPUgk0CT0gKGFueWFycmF5LCBhbnlh
cnJheSksCisJT1BFUkFUT1IJNQlAQCAoYW55YXJyYXksIGFueXF1ZXJ5KSwKKwlGVU5DVElPTgkx
CWJ0dGV4dGNtcCh0ZXh0LCB0ZXh0KSwKKwlGVU5DVElPTgkyCWdpbmFycmF5ZXh0cmFjdChhbnlh
cnJheSwgaW50ZXJuYWwsIGludGVybmFsKSwKKwlGVU5DVElPTgkzCWFueWFycmF5X2dpbl9leHRy
YWN0X3F1ZXJ5X3RleHQodGV4dFtdLCBpbnRlcm5hbCwgc21hbGxpbnQsIGludGVybmFsLCBpbnRl
cm5hbCwgaW50ZXJuYWwsIGludGVybmFsKSwKKwlGVU5DVElPTgk0CWFueWFycmF5X2dpbl9jb25z
aXN0ZW50X3RleHQoaW50ZXJuYWwsIHNtYWxsaW50LCB0ZXh0W10sIGludGVnZXIsIGludGVybmFs
LCBpbnRlcm5hbCwgaW50ZXJuYWwsIGludGVybmFsKSwKKwlTVE9SQUdFCQl0ZXh0OwpkaWZmIC0t
Z2l0IGEvY29udHJpYi9hbnlhcnJheS9hbnlhcnJheS5jIGIvY29udHJpYi9hbnlhcnJheS9hbnlh
cnJheS5jCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAwMDAwLi4wYTJhYjIxNTNj
OAotLS0gL2Rldi9udWxsCisrKyBiL2NvbnRyaWIvYW55YXJyYXkvYW55YXJyYXkuYwpAQCAtMCww
ICsxLDExNiBAQAorLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCisgKgorICogYW55YXJyYXkuYworICoJCUNv
bW1vbiBjb2RlIGZvciB0aGUgYW55YXJyYXkgZXh0ZW5zaW9uLgorICoKKyAqIFRoaXMgZXh0ZW5z
aW9uIGV4dGVuZHMgUG9zdGdyZVNRTCB3aXRoIGludGFycmF5LXN0eWxlIG9wZXJhdGlvbnMgYW5k
CisgKiBpbmRleCBzdXBwb3J0IHRoYXQgd29yayBmb3IgYXJyYXlzIG9mIGFueSBlbGVtZW50IHR5
cGUgd2l0aCBhIGRlZmF1bHQKKyAqIGJ0cmVlIG9wY2xhc3MuICBJdCBpcyBhIGdlbmVyYWxpemF0
aW9uIG9mIHRoZSBjb250cmliL2ludGFycmF5IG1vZHVsZS4KKyAqCisgKiBDb3B5cmlnaHQgKGMp
IDIwMjYsIFBvc3RncmVTUUwgR2xvYmFsIERldmVsb3BtZW50IEdyb3VwCisgKgorICogSURFTlRJ
RklDQVRJT04KKyAqCQljb250cmliL2FueWFycmF5L2FueWFycmF5LmMKKyAqCisgKi0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0KKyAqLworCisjaW5jbHVkZSAicG9zdGdyZXMuaCIKKworI2luY2x1ZGUgImFueWFy
cmF5LmgiCisjaW5jbHVkZSAiY2F0YWxvZy9wZ190eXBlLmgiCisjaW5jbHVkZSAidXRpbHMvYnVp
bHRpbnMuaCIKKyNpbmNsdWRlICJ1dGlscy9sc3lzY2FjaGUuaCIKKworUEdfTU9EVUxFX01BR0lD
X0VYVCgKKwkJCQkJLm5hbWUgPSAiYW55YXJyYXkiLAorCQkJCQkudmVyc2lvbiA9IFBHX1ZFUlNJ
T04KKyk7CisKKy8qCisgKiBhbnlhcnJheV9nZXRfbWV0YQorICoJCUZldGNoIChhbmQgY2FjaGUp
IHR5cGUgbWV0YWRhdGEgZm9yIHRoZSBnaXZlbiBlbGVtZW50IHR5cGUuCisgKgorICogVGhlIGNh
Y2hlIGxpdmVzIGluIGZjaW5mby0+ZmxpbmZvLT5mbl9leHRyYSBzbyB3ZSBwYXkgdGhlIGNhdGFs
b2cgbG9va3VwCisgKiBjb3N0IG9ubHkgb25jZSBwZXIgY2FsbCBzaXRlLiAgSWYgIm5lZWRfaGFz
aCIgaXMgdHJ1ZSB0aGUgZWxlbWVudCB0eXBlCisgKiBtdXN0IGFkZGl0aW9uYWxseSBwcm92aWRl
IGEgZGVmYXVsdCBoYXNoIGZ1bmN0aW9uOyBvdGhlcndpc2Ugb25seSBhIGJ0cmVlCisgKiBjb21w
YXJpc29uIGZ1bmN0aW9uIGlzIHJlcXVpcmVkLgorICovCitBbnlBcnJheVR5cGVJbmZvICoKK2Fu
eWFycmF5X2dldF9tZXRhKEZ1bmN0aW9uQ2FsbEluZm8gZmNpbmZvLCBPaWQgZWxlbWVudF90eXBl
LCBib29sIG5lZWRfaGFzaCkKK3sKKwlBbnlBcnJheVR5cGVJbmZvICptZXRhID0gKEFueUFycmF5
VHlwZUluZm8gKikgZmNpbmZvLT5mbGluZm8tPmZuX2V4dHJhOworCVR5cGVDYWNoZUVudHJ5ICp0
eXBlbnRyeTsKKwl1aW50MzIJCWZsYWdzOworCisJaWYgKG1ldGEgPT0gTlVMTCkKKwl7CisJCW1l
dGEgPSAoQW55QXJyYXlUeXBlSW5mbyAqKQorCQkJTWVtb3J5Q29udGV4dEFsbG9jWmVybyhmY2lu
Zm8tPmZsaW5mby0+Zm5fbWN4dCwKKwkJCQkJCQkJICAgc2l6ZW9mKEFueUFycmF5VHlwZUluZm8p
KTsKKwkJZmNpbmZvLT5mbGluZm8tPmZuX2V4dHJhID0gbWV0YTsKKwkJbWV0YS0+ZWxlbWVudF90
eXBlID0gSW52YWxpZE9pZDsKKwl9CisKKwlpZiAobWV0YS0+ZWxlbWVudF90eXBlID09IGVsZW1l
bnRfdHlwZSAmJiAoIW5lZWRfaGFzaCB8fCBtZXRhLT5oYXZlX2hhc2gpKQorCQlyZXR1cm4gbWV0
YTsKKworCWZsYWdzID0gVFlQRUNBQ0hFX0NNUF9QUk9DX0ZJTkZPIHwgVFlQRUNBQ0hFX0VRX09Q
Ul9GSU5GTzsKKwlpZiAobmVlZF9oYXNoKQorCQlmbGFncyB8PSBUWVBFQ0FDSEVfSEFTSF9QUk9D
X0ZJTkZPOworCisJdHlwZW50cnkgPSBsb29rdXBfdHlwZV9jYWNoZShlbGVtZW50X3R5cGUsIGZs
YWdzKTsKKworCWlmICghT2lkSXNWYWxpZCh0eXBlbnRyeS0+Y21wX3Byb2NfZmluZm8uZm5fb2lk
KSkKKwkJZXJlcG9ydChFUlJPUiwKKwkJCQkoZXJyY29kZShFUlJDT0RFX1VOREVGSU5FRF9GVU5D
VElPTiksCisJCQkJIGVycm1zZygiY291bGQgbm90IGlkZW50aWZ5IGEgY29tcGFyaXNvbiBmdW5j
dGlvbiBmb3IgdHlwZSAlcyIsCisJCQkJCQlmb3JtYXRfdHlwZV9iZShlbGVtZW50X3R5cGUpKSkp
OworCisJaWYgKCFPaWRJc1ZhbGlkKHR5cGVudHJ5LT5lcV9vcHJfZmluZm8uZm5fb2lkKSkKKwkJ
ZXJlcG9ydChFUlJPUiwKKwkJCQkoZXJyY29kZShFUlJDT0RFX1VOREVGSU5FRF9GVU5DVElPTiks
CisJCQkJIGVycm1zZygiY291bGQgbm90IGlkZW50aWZ5IGFuIGVxdWFsaXR5IG9wZXJhdG9yIGZv
ciB0eXBlICVzIiwKKwkJCQkJCWZvcm1hdF90eXBlX2JlKGVsZW1lbnRfdHlwZSkpKSk7CisKKwlp
ZiAobmVlZF9oYXNoICYmICFPaWRJc1ZhbGlkKHR5cGVudHJ5LT5oYXNoX3Byb2NfZmluZm8uZm5f
b2lkKSkKKwkJZXJlcG9ydChFUlJPUiwKKwkJCQkoZXJyY29kZShFUlJDT0RFX1VOREVGSU5FRF9G
VU5DVElPTiksCisJCQkJIGVycm1zZygiY291bGQgbm90IGlkZW50aWZ5IGEgaGFzaCBmdW5jdGlv
biBmb3IgdHlwZSAlcyIsCisJCQkJCQlmb3JtYXRfdHlwZV9iZShlbGVtZW50X3R5cGUpKSkpOwor
CisJbWV0YS0+ZWxlbWVudF90eXBlID0gZWxlbWVudF90eXBlOworCWdldF90eXBsZW5ieXZhbGFs
aWduKGVsZW1lbnRfdHlwZSwgJm1ldGEtPnR5cGxlbiwgJm1ldGEtPnR5cGJ5dmFsLAorCQkJCQkJ
ICZtZXRhLT50eXBhbGlnbik7CisJbWV0YS0+dHlwY29sbGF0aW9uID0gdHlwZW50cnktPnR5cGNv
bGxhdGlvbjsKKwlmbWdyX2luZm9fY3h0KHR5cGVudHJ5LT5jbXBfcHJvY19maW5mby5mbl9vaWQs
ICZtZXRhLT5jbXBfcHJvYywKKwkJCQkgIGZjaW5mby0+ZmxpbmZvLT5mbl9tY3h0KTsKKwlmbWdy
X2luZm9fY3h0KHR5cGVudHJ5LT5lcV9vcHJfZmluZm8uZm5fb2lkLCAmbWV0YS0+ZXFfcHJvYywK
KwkJCQkgIGZjaW5mby0+ZmxpbmZvLT5mbl9tY3h0KTsKKwlpZiAobmVlZF9oYXNoKQorCXsKKwkJ
Zm1ncl9pbmZvX2N4dCh0eXBlbnRyeS0+aGFzaF9wcm9jX2ZpbmZvLmZuX29pZCwgJm1ldGEtPmhh
c2hfcHJvYywKKwkJCQkJICBmY2luZm8tPmZsaW5mby0+Zm5fbWN4dCk7CisJCW1ldGEtPmhhdmVf
aGFzaCA9IHRydWU7CisJfQorCWVsc2UKKwkJbWV0YS0+aGF2ZV9oYXNoID0gZmFsc2U7CisKKwly
ZXR1cm4gbWV0YTsKK30KKworLyoKKyAqIGFueWFycmF5X2NtcF9kYXR1bQorICoJCXFzb3J0X2Fy
Zy1jb21wYXRpYmxlIGNvbXBhcmF0b3IgZGVsZWdhdGluZyB0byB0aGUgdHlwZSdzIGJ0cmVlIGNt
cC4KKyAqLworaW50CithbnlhcnJheV9jbXBfZGF0dW0oY29uc3Qgdm9pZCAqYSwgY29uc3Qgdm9p
ZCAqYiwgdm9pZCAqYXJnKQoreworCUFueUFycmF5VHlwZUluZm8gKm1ldGEgPSAoQW55QXJyYXlU
eXBlSW5mbyAqKSBhcmc7CisJRGF0dW0JCWQxID0gKigoY29uc3QgRGF0dW0gKikgYSk7CisJRGF0
dW0JCWQyID0gKigoY29uc3QgRGF0dW0gKikgYik7CisJRGF0dW0JCXJlc3VsdDsKKworCXJlc3Vs
dCA9IEZ1bmN0aW9uQ2FsbDJDb2xsKCZtZXRhLT5jbXBfcHJvYywgbWV0YS0+dHlwY29sbGF0aW9u
LCBkMSwgZDIpOworCXJldHVybiBEYXR1bUdldEludDMyKHJlc3VsdCk7Cit9CmRpZmYgLS1naXQg
YS9jb250cmliL2FueWFycmF5L2FueWFycmF5LmNvbnRyb2wgYi9jb250cmliL2FueWFycmF5L2Fu
eWFycmF5LmNvbnRyb2wKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAuLjI0
NzhmMmQ5M2Q3Ci0tLSAvZGV2L251bGwKKysrIGIvY29udHJpYi9hbnlhcnJheS9hbnlhcnJheS5j
b250cm9sCkBAIC0wLDAgKzEsNiBAQAorIyBhbnlhcnJheSBleHRlbnNpb24KK2NvbW1lbnQgPSAn
T3BlcmF0aW9ucyBhbmQgaW5kZXhlcyBmb3IgYXJyYXlzIG9mIGFueSB0eXBlJworZGVmYXVsdF92
ZXJzaW9uID0gJzEuMCcKK21vZHVsZV9wYXRobmFtZSA9ICckbGliZGlyL2FueWFycmF5JworcmVs
b2NhdGFibGUgPSB0cnVlCit0cnVzdGVkID0gZmFsc2UKZGlmZiAtLWdpdCBhL2NvbnRyaWIvYW55
YXJyYXkvYW55YXJyYXkuaCBiL2NvbnRyaWIvYW55YXJyYXkvYW55YXJyYXkuaApuZXcgZmlsZSBt
b2RlIDEwMDY0NAppbmRleCAwMDAwMDAwMDAwMC4uZjU5YWM5ZGU3NDkKLS0tIC9kZXYvbnVsbAor
KysgYi9jb250cmliL2FueWFycmF5L2FueWFycmF5LmgKQEAgLTAsMCArMSwxODQgQEAKKy8qLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLQorICoKKyAqIGFueWFycmF5LmgKKyAqCQlTaGFyZWQgZGVjbGFyYXRpb25z
IGZvciB0aGUgYW55YXJyYXkgZXh0ZW5zaW9uLgorICoKKyAqIENvcHlyaWdodCAoYykgMjAyNiwg
UG9zdGdyZVNRTCBHbG9iYWwgRGV2ZWxvcG1lbnQgR3JvdXAKKyAqCisgKiBJREVOVElGSUNBVElP
TgorICoJCWNvbnRyaWIvYW55YXJyYXkvYW55YXJyYXkuaAorICoKKyAqLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LQorICovCisjaWZuZGVmIEFOWUFSUkFZX0gKKyNkZWZpbmUgQU5ZQVJSQVlfSAorCisjaW5jbHVk
ZSAiYWNjZXNzL2dpc3QuaCIKKyNpbmNsdWRlICJmbWdyLmgiCisjaW5jbHVkZSAidXRpbHMvYXJy
YXkuaCIKKyNpbmNsdWRlICJ1dGlscy90eXBjYWNoZS5oIgorCisvKgorICogUGVyLWNhbGwgY2Fj
aGVkIGVsZW1lbnQgdHlwZSBtZXRhZGF0YS4KKyAqCisgKiBTdG9yZWQgaW4gZmNpbmZvLT5mbGlu
Zm8tPmZuX2V4dHJhIHNvIHdlIGxvb2sgdXAgdGhlIHR5cGUgb25jZSBwZXIKKyAqIHBsYW5uZXIt
bGV2ZWwgY2FsbCBzaXRlLiAgQWxsIGVudHJpZXMgYXJlIHBvcHVsYXRlZCBieSBhbnlhcnJheV9n
ZXRfbWV0YSgpLgorICovCit0eXBlZGVmIHN0cnVjdCBBbnlBcnJheVR5cGVJbmZvCit7CisJT2lk
CQkJZWxlbWVudF90eXBlOwkvKiBlbGVtZW50IE9JRCwgb3IgSW52YWxpZE9pZCBpZiBub3QKKwkJ
CQkJCQkJICogaW5pdGlhbGl6ZWQgKi8KKwlpbnQxNgkJdHlwbGVuOworCWJvb2wJCXR5cGJ5dmFs
OworCWNoYXIJCXR5cGFsaWduOworCU9pZAkJCXR5cGNvbGxhdGlvbjsJLyogZGVmYXVsdCBjb2xs
YXRpb24gZm9yIGNvbXBhcmlzb25zICovCisJRm1nckluZm8JY21wX3Byb2M7CQkvKiBidHJlZSBj
b21wYXJpc29uIGZ1bmN0aW9uIGZvciBlbGVtZW50X3R5cGUgKi8KKwlGbWdySW5mbwllcV9wcm9j
OwkJLyogZXF1YWxpdHkgZnVuY3Rpb24gZm9yIGVsZW1lbnRfdHlwZSAqLworCUZtZ3JJbmZvCWhh
c2hfcHJvYzsJCS8qIGhhc2ggZnVuY3Rpb24gZm9yIGVsZW1lbnRfdHlwZSAob3B0aW9uYWwpICov
CisJYm9vbAkJaGF2ZV9oYXNoOwkJLyogd2hldGhlciBoYXNoX3Byb2Mgd2FzIGZpbGxlZCBpbiAq
LworfSBBbnlBcnJheVR5cGVJbmZvOworCisvKiBSZWplY3QgdGhlIGtpbmRzIG9mIGlucHV0IHdl
IGRvIG5vdCBoYW5kbGUuICovCisjZGVmaW5lIEFOWUFSUkFZX0NIRUNLX0FSUkFZKGFycikgXAor
CWRvIHsgXAorCQlpZiAoQVJSX05ESU0oYXJyKSA+IDEpIFwKKwkJCWVyZXBvcnQoRVJST1IsIFwK
KwkJCQkJKGVycmNvZGUoRVJSQ09ERV9GRUFUVVJFX05PVF9TVVBQT1JURUQpLCBcCisJCQkJCSBl
cnJtc2coIm11bHRpZGltZW5zaW9uYWwgYXJyYXlzIGFyZSBub3Qgc3VwcG9ydGVkIikpKTsgXAor
CQlpZiAoQVJSX0hBU05VTEwoYXJyKSAmJiBhcnJheV9jb250YWluc19udWxscyhhcnIpKSBcCisJ
CQllcmVwb3J0KEVSUk9SLCBcCisJCQkJCShlcnJjb2RlKEVSUkNPREVfTlVMTF9WQUxVRV9OT1Rf
QUxMT1dFRCksIFwKKwkJCQkJIGVycm1zZygiYXJyYXkgbXVzdCBub3QgY29udGFpbiBudWxscyIp
KSk7IFwKKwl9IHdoaWxlICgwKQorCisjZGVmaW5lIEFOWUFSUkFZX05FTEVNUyhhcnIpIFwKKwko
QVJSX05ESU0oYXJyKSA+IDAgPyBBcnJheUdldE5JdGVtcyhBUlJfTkRJTShhcnIpLCBBUlJfRElN
UyhhcnIpKSA6IDApCisKKy8qCisgKiBJbml0aWFsaXplIC8gcmVmcmVzaCBBbnlBcnJheVR5cGVJ
bmZvIGZvciBhIGdpdmVuIGVsZW1lbnQgdHlwZS4KKyAqCisgKiBBbGxvY2F0ZXMgdGhlIHN0cnVj
dCBpbiBmY2luZm8tPmZsaW5mby0+Zm5fbWN4dCBvbiBmaXJzdCB1c2U7IG9uIHN1YnNlcXVlbnQK
KyAqIGNhbGxzIHJldXNlcyB0aGUgY2FjaGUgdW5sZXNzIHRoZSBlbGVtZW50IHR5cGUgY2hhbmdl
ZC4gIFJlcG9ydHMgYW4gZXJyb3IKKyAqIHZpYSBlcmVwb3J0KCkgaWYgdGhlIGVsZW1lbnQgdHlw
ZSBsYWNrcyBhIGJ0cmVlIGNvbXBhcmlzb24gb3BlcmF0b3IKKyAqIChuZWVkX2hhc2ggPT0gdHJ1
ZSBhZGRpdGlvbmFsbHkgcmVxdWlyZXMgYSBoYXNoIGZ1bmN0aW9uKS4KKyAqLworZXh0ZXJuIEFu
eUFycmF5VHlwZUluZm8gKmFueWFycmF5X2dldF9tZXRhKEZ1bmN0aW9uQ2FsbEluZm8gZmNpbmZv
LAorCQkJCQkJCQkJCSAgIE9pZCBlbGVtZW50X3R5cGUsCisJCQkJCQkJCQkJICAgYm9vbCBuZWVk
X2hhc2gpOworCisvKgorICogQ29tcGFyaXNvbiBoZWxwZXIgdXNlZCBib3RoIGFzIGEgcXNvcnRf
YXJnIGNhbGxiYWNrIGFuZCBkaXJlY3RseS4KKyAqICJhcmciIG11c3QgYmUgYSB2YWxpZCBBbnlB
cnJheVR5cGVJbmZvICouCisgKi8KK2V4dGVybiBpbnQJYW55YXJyYXlfY21wX2RhdHVtKGNvbnN0
IHZvaWQgKmEsIGNvbnN0IHZvaWQgKmIsIHZvaWQgKmFyZyk7CisKKy8qKioqKioqKioqKioqKioq
KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKgorICogIEJvb2xlYW4gcXVlcnkgdHlwZQorICoKKyAqICBBbiBhbnlxdWVyeSB2YWx1ZSBp
cyBhIGJvb2xlYW4gZXhwcmVzc2lvbiBpbiBwb3N0Zml4IG5vdGF0aW9uIHdob3NlIGxlYXZlcwor
ICogIGFyZSB0ZXh0dWFsIHJlcHJlc2VudGF0aW9ucyBvZiB2YWx1ZXMuICBUaGUgZWxlbWVudCB0
eXBlIGlzIG5vdCBrbm93biBhdAorICogIHBhcnNlIHRpbWU7IGl0IGlzIHN1cHBsaWVkIGF0IEBA
LXRpbWUgYnkgdGhlIGFycmF5IG9wZXJhbmQsIGFuZCB0aGUgdmFsdWUKKyAqICBzdHJpbmdzIGFy
ZSBwYXJzZWQgbGF6aWx5IHRocm91Z2ggdGhlIGVsZW1lbnQgdHlwZSdzIHRleHQgaW5wdXQgZnVu
Y3Rpb24uCisgKgorICogIE9uLWRpc2sgbGF5b3V0OgorICoKKyAqICAgICArLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0rCisgKiAgICAgfCB2YXJsZW5hIGhlYWRlciAgICAgICAgICAgICAg
fAorICogICAgIHwgaW50MzIgIHNpemUgICAgICAobiBpdGVtcykgIHwKKyAqICAgICB8IGludDMy
ICBzdHJfb2ZmICAgICAgICAgICAgICB8ICAtLSBieXRlIG9mZnNldCB0byBzdHJpbmcgaGVhcAor
ICogICAgIHwgaW50MzIgIHN0cl9sZW4gICAgICAgICAgICAgIHwKKyAqICAgICB8IEFueVF1ZXJ5
SXRlbSBpdGVtc1tzaXplXSAgICB8CisgKiAgICAgfCA8cGFkZGluZz4gICAgICAgICAgICAgICAg
ICAgfAorICogICAgIHwgY2hhciAgIHN0cmluZ3Nbc3RyX2xlbl0gICAgIHwgIC0tIG51bGwtdGVy
bWluYXRlZCB2YWx1ZSBzdHJpbmdzCisgKiAgICAgKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tKworICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKioqKioqKioqKioqKioqKioqKioqKioqLworCisvKiBpdGVtLnR5cGUgdmFsdWVzICovCisj
ZGVmaW5lIEFOWVFfVkFMCTEKKyNkZWZpbmUgQU5ZUV9PUFIJMgorCisvKiBvcGVyYXRvciBjb2Rl
cyAoYWxzbyB1c2VkIGluIHRoZSBpbnB1dCBncmFtbWFyKSAqLworI2RlZmluZSBBTllRX0FORAkn
JicKKyNkZWZpbmUgQU5ZUV9PUgkJJ3wnCisjZGVmaW5lIEFOWVFfTk9UCSchJworCit0eXBlZGVm
IHN0cnVjdCBBbnlRdWVyeUl0ZW0KK3sKKwlpbnQxNgkJdHlwZTsJCQkvKiBBTllRX1ZBTCBvciBB
TllRX09QUiAqLworCWludDE2CQlsZWZ0OwkJCS8qIG9mZnNldCB0byBsZWZ0LW9wZXJhbmQgaXRl
bSAoT1BSIG9ubHkpICovCisJaW50MzIJCXBheWxvYWQ7CQkvKiBWQUw6IG9mZnNldCBpbnRvIHN0
cmluZyBoZWFwOyBPUFI6IG9uZSBvZgorCQkJCQkJCQkgKiBBTllRX0FORC9PUi9OT1QgKi8KK30g
QW55UXVlcnlJdGVtOworCit0eXBlZGVmIHN0cnVjdCBBbnlRdWVyeQoreworCWludDMyCQl2bF9s
ZW5fOwkJLyogdmFybGVuYSBoZWFkZXIgKGRvIG5vdCB0b3VjaCBkaXJlY3RseSEpICovCisJaW50
MzIJCXNpemU7CQkJLyogbnVtYmVyIG9mIGl0ZW1zICovCisJaW50MzIJCXN0cl9vZmY7CQkvKiBi
eXRlIG9mZnNldCB0byBzdHJpbmcgaGVhcCAqLworCWludDMyCQlzdHJfbGVuOwkJLyogbGVuZ3Ro
IG9mIHN0cmluZyBoZWFwICovCisJQW55UXVlcnlJdGVtIGl0ZW1zW0ZMRVhJQkxFX0FSUkFZX01F
TUJFUl07CisJLyogZm9sbG93ZWQgYnkgbnVsbC10ZXJtaW5hdGVkIHZhbHVlIHN0cmluZ3MgKi8K
K30gQW55UXVlcnk7CisKKyNkZWZpbmUgQU5ZUVVFUllfSERSU0laRQkJCW9mZnNldG9mKEFueVF1
ZXJ5LCBpdGVtcykKKyNkZWZpbmUgQU5ZUVVFUllfSVRFTVMocSkJCQkoKHEpLT5pdGVtcykKKyNk
ZWZpbmUgQU5ZUVVFUllfU1RSSU5HKHEsIGl0ZW0pCSgoY29uc3QgY2hhciAqKSAocSkgKyAocSkt
PnN0cl9vZmYgKyAoaXRlbSktPnBheWxvYWQpCisjZGVmaW5lIEFOWVFVRVJZX01BWElURU1TIFwK
KwkoKE1heEFsbG9jU2l6ZSAtIEFOWVFVRVJZX0hEUlNJWkUpIC8gc2l6ZW9mKEFueVF1ZXJ5SXRl
bSkpCisKKyNkZWZpbmUgRGF0dW1HZXRBbnlRdWVyeVAoWCkJCSgoQW55UXVlcnkgKikgUEdfREVU
T0FTVF9EQVRVTShYKSkKKyNkZWZpbmUgUEdfR0VUQVJHX0FOWVFVRVJZX1AobikJCURhdHVtR2V0
QW55UXVlcnlQKFBHX0dFVEFSR19EQVRVTShuKSkKKworLyoqKioqKioqKioqKioqKioqKioqKioq
KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCisg
KiAgR2lTVCBzaWduYXR1cmUga2V5CisgKgorICogIEVhY2ggaW5kZXhlZCBhcnJheSBpcyBzdW1t
YXJpemVkIGFzIGEgZml4ZWQtc2l6ZSBiaXQgdmVjdG9yICgic2lnbmF0dXJlIikuCisgKiAgRWFj
aCBlbGVtZW50IGNvbnRyaWJ1dGVzIGEgc2luZ2xlIGJpdCwgY2hvc2VuIGFzCisgKiAgICAgIGhh
c2goZWxlbWVudCkgbW9kIChzaWdsZW4gKiA4KS4KKyAqICBJbnRlcm5hbCBub2RlIGtleXMgYXJl
IGJpdHdpc2UgdW5pb25zIG9mIHRoZWlyIGNoaWxkcmVuOyB0aGUgQUxMSVNUUlVFCisgKiAgZmxh
ZyBzaG9ydC1jaXJjdWl0cyBzdG9yYWdlIHdoZW4gZXZlcnkgYml0IHdvdWxkIGJlIHNldC4KKyAq
KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKioqKioqKioqKioqKioqKi8KKworI2RlZmluZSBBTllBUlJBWV9TSUdMRU5fREVGQVVMVAkJ
KDYzICogNCkJLyogMjUyIGJ5dGVzIC0+IDIwMTYgYml0cyAqLworI2RlZmluZSBBTllBUlJBWV9T
SUdMRU5fTUFYCQkJR0lTVE1heEluZGV4S2V5U2l6ZQorI2RlZmluZSBBTllBUlJBWV9BTExJU1RS
VUUJCQkweDAxCisKK3R5cGVkZWYgc3RydWN0IEFueUFycmF5R2lzdEtleQoreworCWludDMyCQl2
bF9sZW5fOwkJLyogdmFybGVuYSBoZWFkZXIgKGRvIG5vdCB0b3VjaCBkaXJlY3RseSEpICovCisJ
aW50MzIJCWZsYWc7CisJY2hhcgkJZGF0YVtGTEVYSUJMRV9BUlJBWV9NRU1CRVJdOwkvKiBiaXQg
dmVjdG9yLCBzaWdsZW4gYnl0ZXMgKi8KK30gQW55QXJyYXlHaXN0S2V5OworCit0eXBlZGVmIHN0
cnVjdCBBbnlBcnJheUdpc3RPcHRpb25zCit7CisJaW50MzIJCXZsX2xlbl87CisJaW50CQkJc2ln
bGVuOwkJCS8qIHNpZ25hdHVyZSBsZW5ndGggaW4gYnl0ZXMgKi8KK30gQW55QXJyYXlHaXN0T3B0
aW9uczsKKworI2RlZmluZSBBTllBUlJBWV9HRVRfU0lHTEVOKCkJCShQR19IQVNfT1BDTEFTU19P
UFRJT05TKCkgPyBcCisJCQkJCQkJCQkgKChBbnlBcnJheUdpc3RPcHRpb25zICopIFBHX0dFVF9P
UENMQVNTX09QVElPTlMoKSktPnNpZ2xlbiA6IFwKKwkJCQkJCQkJCSBBTllBUlJBWV9TSUdMRU5f
REVGQVVMVCkKKworI2RlZmluZSBBTllBUlJBWV9HS0VZX0hEUgkJCShWQVJIRFJTWiArIHNpemVv
ZihpbnQzMikpCisjZGVmaW5lIEFOWUFSUkFZX0dLRVlfU0laRShmbGFnLCBzaWdsZW4pIFwKKwko
QU5ZQVJSQVlfR0tFWV9IRFIgKyAoKChmbGFnKSAmIEFOWUFSUkFZX0FMTElTVFJVRSkgPyAwIDog
KHNpZ2xlbikpKQorI2RlZmluZSBBTllBUlJBWV9HS0VZX0lTQUxMVFJVRShrKQkoKChBbnlBcnJh
eUdpc3RLZXkgKikgKGspKS0+ZmxhZyAmIEFOWUFSUkFZX0FMTElTVFJVRSkKKyNkZWZpbmUgQU5Z
QVJSQVlfR0tFWV9TSUdOKGspCQkoKHVuc2lnbmVkIGNoYXIgKikgKCgoQW55QXJyYXlHaXN0S2V5
ICopIChrKSktPmRhdGEpKQorCisvKiBHSU4gc3RyYXRlZ3kgbnVtYmVyczsgdGhlIGZpcnN0IGZv
dXIgbWF0Y2ggY29yZSdzIGdpbi9hcnJheV9vcHMgKi8KKyNkZWZpbmUgQU5ZQVJSQVlfR0lOX09W
RVJMQVBfU1RSQVRFR1kJMQorI2RlZmluZSBBTllBUlJBWV9HSU5fQ09OVEFJTlNfU1RSQVRFR1kJ
MgorI2RlZmluZSBBTllBUlJBWV9HSU5fQ09OVEFJTkVEX1NUUkFURUdZCTMKKyNkZWZpbmUgQU5Z
QVJSQVlfR0lOX0VRVUFMX1NUUkFURUdZCQk0CisjZGVmaW5lIEFOWUFSUkFZX0dJTl9CT09MRUFO
X1NUUkFURUdZCTUKKworI2RlZmluZSBBTllBUlJBWV9IQVNIVkFMKGgsIHNpZ2xlbikJKCh1bnNp
Z25lZCBpbnQpIChoKSAlICgoc2lnbGVuKSAqIEJJVFNfUEVSX0JZVEUpKQorI2RlZmluZSBBTllB
UlJBWV9TRVRCSVQoc2lnLCBoLCBzaWdsZW4pIFwKKwkoKHNpZylbKEFOWUFSUkFZX0hBU0hWQUwo
KGgpLCAoc2lnbGVuKSkgLyBCSVRTX1BFUl9CWVRFKV0gfD0gXAorCQkoMSA8PCAoQU5ZQVJSQVlf
SEFTSFZBTCgoaCksIChzaWdsZW4pKSAlIEJJVFNfUEVSX0JZVEUpKSkKKyNkZWZpbmUgQU5ZQVJS
QVlfR0VUQklUKHNpZywgaCwgc2lnbGVuKSBcCisJKCgoc2lnKVsoQU5ZQVJSQVlfSEFTSFZBTCgo
aCksIChzaWdsZW4pKSAvIEJJVFNfUEVSX0JZVEUpXSA+PiBcCisJCShBTllBUlJBWV9IQVNIVkFM
KChoKSwgKHNpZ2xlbikpICUgQklUU19QRVJfQllURSkpICYgMSkKKworI2VuZGlmCQkJCQkJCS8q
IEFOWUFSUkFZX0ggKi8KZGlmZiAtLWdpdCBhL2NvbnRyaWIvYW55YXJyYXkvYW55YXJyYXlfYm9v
bC5jIGIvY29udHJpYi9hbnlhcnJheS9hbnlhcnJheV9ib29sLmMKbmV3IGZpbGUgbW9kZSAxMDA2
NDQKaW5kZXggMDAwMDAwMDAwMDAuLjMyNTYxOTgzN2VmCi0tLSAvZGV2L251bGwKKysrIGIvY29u
dHJpYi9hbnlhcnJheS9hbnlhcnJheV9ib29sLmMKQEAgLTAsMCArMSw2NjQgQEAKKy8qLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLQorICoKKyAqIGFueWFycmF5X2Jvb2wuYworICoJCUJvb2xlYW4gcXVlcnkgdHlw
ZSBmb3IgYW55YXJyYXkuCisgKgorICogUHJvdmlkZXMgdGhlIGFueXF1ZXJ5IHR5cGUgYW5kIHRo
ZSBAQCBvcGVyYXRvci4gIEEgcXVlcnkgdmFsdWUgaXMgYQorICogYm9vbGVhbiBleHByZXNzaW9u
IHdob3NlIGxlYXZlcyBhcmUgdGV4dCB0b2tlbnM7IHRoZSBlbGVtZW50IHR5cGUgaXMKKyAqIHN1
cHBsaWVkIGF0IEBALXRpbWUgYnkgdGhlIGFycmF5IG9wZXJhbmQsIGFuZCB0aGUgbGVhdmVzIGFy
ZSBwYXJzZWQKKyAqIHRocm91Z2ggdGhlIGVsZW1lbnQgdHlwZSdzIHRleHQgaW5wdXQgZnVuY3Rp
b24uCisgKgorICogR3JhbW1hcjoKKyAqCisgKgkgIGV4cHIgICAgICAgIDo6PSBvcl9leHByCisg
KgkgIG9yX2V4cHIgICAgIDo6PSBhbmRfZXhwciAoICd8JyBhbmRfZXhwciApKgorICoJICBhbmRf
ZXhwciAgICA6Oj0gdW5hcnlfZXhwciAoICcmJyB1bmFyeV9leHByICkqCisgKgkgIHVuYXJ5X2V4
cHIgIDo6PSAnIScgdW5hcnlfZXhwciB8IGF0b20KKyAqCSAgYXRvbSAgICAgICAgOjo9IFZBTFVF
IHwgJygnIGV4cHIgJyknCisgKgkgIFZBTFVFICAgICAgIDo6PSBiYXJlX3Rva2VuIHwgcXVvdGVk
X3N0cmluZworICoJICBiYXJlX3Rva2VuICA6Oj0gYW55IHJ1biBvZiBjaGFyYWN0ZXJzIHRoYXQg
YXJlIG5vdCB3aGl0ZXNwYWNlLAorICoJICAgICAgICAgICAgICAgICAgJyYnLCAnfCcsICchJywg
JygnLCAnKScsIG9yICciJworICoJICBxdW90ZWRfc3RyaW5nIDo9ICciJyBjaGFycy13aXRoLWJh
Y2tzbGFzaC1lc2NhcGVzICciJworICoKKyAqCisgKiBDb3B5cmlnaHQgKGMpIDIwMjYsIFBvc3Rn
cmVTUUwgR2xvYmFsIERldmVsb3BtZW50IEdyb3VwCisgKgorICogSURFTlRJRklDQVRJT04KKyAq
CQljb250cmliL2FueWFycmF5L2FueWFycmF5X2Jvb2wuYworICoKKyAqLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LQorICovCisKKyNpbmNsdWRlICJwb3N0Z3Jlcy5oIgorCisjaW5jbHVkZSAiYW55YXJyYXkuaCIK
KworI2luY2x1ZGUgImxpYi9zdHJpbmdpbmZvLmgiCisjaW5jbHVkZSAibWlzY2FkbWluLmgiCisj
aW5jbHVkZSAibm9kZXMvbWlzY25vZGVzLmgiCisjaW5jbHVkZSAidXRpbHMvYXJyYXkuaCIKKyNp
bmNsdWRlICJ1dGlscy9idWlsdGlucy5oIgorI2luY2x1ZGUgInV0aWxzL2xzeXNjYWNoZS5oIgor
I2luY2x1ZGUgInV0aWxzL21lbXV0aWxzLmgiCisKK1BHX0ZVTkNUSU9OX0lORk9fVjEoYW55cXVl
cnlfaW4pOworUEdfRlVOQ1RJT05fSU5GT19WMShhbnlxdWVyeV9vdXQpOworUEdfRlVOQ1RJT05f
SU5GT19WMShhbnlhcnJheV9ib29sb3ApOworUEdfRlVOQ1RJT05fSU5GT19WMShhbnlxdWVyeV9i
b29sb3BfcmV2KTsKK1BHX0ZVTkNUSU9OX0lORk9fVjEoYW55cXVlcnlfcXVlcnl0cmVlKTsKKwor
CisvKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0KKyAqICBQYXJzZXIKKyAqIC0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQorICov
CisKKy8qCisgKiBXb3JraW5nIHN0YXRlIHVzZWQgd2hpbGUgYnVpbGRpbmcgdGhlIHBvc3RmaXgg
aXRlbSBsaXN0LgorICoKKyAqIEl0ZW1zIGFyZSBlbWl0dGVkIGluIHBvc3RmaXggKHJldmVyc2Ug
cG9saXNoKSBvcmRlciBkaXJlY3RseSBpbnRvIHRoZQorICogIml0ZW1zIiBhcnJheS4gIFZhbHVl
IHN0cmluZ3MgYXJlIGNvbmNhdGVuYXRlZCBpbnRvICJzdHJzIjsgZWFjaCBWQUwgaXRlbQorICog
c3RvcmVzIHRoZSBieXRlIG9mZnNldCBvZiBpdHMgc3RyaW5nIHdpdGhpbiBzdHJzLT5kYXRhLgor
ICovCit0eXBlZGVmIHN0cnVjdCBQYXJzZXJTdGF0ZQoreworCWNvbnN0IGNoYXIgKmN1cjsKKwlj
b25zdCBjaGFyICplbmQ7CisJQW55UXVlcnlJdGVtICppdGVtczsKKwlpbnQJCQluaXRlbXM7CisJ
aW50CQkJY2FwaXRlbXM7CisJU3RyaW5nSW5mb0RhdGEgc3RyczsKKwlzdHJ1Y3QgTm9kZSAqZXNj
b250ZXh0OworfSBQYXJzZXJTdGF0ZTsKKworI2RlZmluZSBQQVJTRV9GQUlMKHN0YXRlLCBlcnJj
LCAuLi4pIFwKKwlkbyB7IFwKKwkJZXJyc2F2ZSgoc3RhdGUpLT5lc2NvbnRleHQsIFwKKwkJCQko
ZXJyY29kZShlcnJjKSwgXAorCQkJCSBfX1ZBX0FSR1NfXykpOyBcCisJCXJldHVybiBmYWxzZTsg
XAorCX0gd2hpbGUgKDApCisKK3N0YXRpYyBib29sIHBhcnNlX2V4cHIoUGFyc2VyU3RhdGUgKnN0
YXRlKTsKKworc3RhdGljIHZvaWQKK3NraXBfd3MoUGFyc2VyU3RhdGUgKnN0YXRlKQoreworCXdo
aWxlIChzdGF0ZS0+Y3VyIDwgc3RhdGUtPmVuZCAmJgorCQkgICAoKnN0YXRlLT5jdXIgPT0gJyAn
IHx8ICpzdGF0ZS0+Y3VyID09ICdcdCcgfHwKKwkJCSpzdGF0ZS0+Y3VyID09ICdccicgfHwgKnN0
YXRlLT5jdXIgPT0gJ1xuJyB8fAorCQkJKnN0YXRlLT5jdXIgPT0gJ1x2JyB8fCAqc3RhdGUtPmN1
ciA9PSAnXGYnKSkKKwkJc3RhdGUtPmN1cisrOworfQorCitzdGF0aWMgYm9vbAoraXNfdmFsdWVf
Y2hhcihjaGFyIGMpCit7CisJaWYgKGMgPT0gJ1wwJyB8fCBjID09ICcgJyB8fCBjID09ICdcdCcg
fHwgYyA9PSAnXHInIHx8IGMgPT0gJ1xuJyB8fAorCQljID09ICdcdicgfHwgYyA9PSAnXGYnKQor
CQlyZXR1cm4gZmFsc2U7CisJaWYgKGMgPT0gJyYnIHx8IGMgPT0gJ3wnIHx8IGMgPT0gJyEnIHx8
IGMgPT0gJygnIHx8IGMgPT0gJyknIHx8IGMgPT0gJyInKQorCQlyZXR1cm4gZmFsc2U7CisJcmV0
dXJuIHRydWU7Cit9CisKK3N0YXRpYyBib29sCitlbWl0X2l0ZW0oUGFyc2VyU3RhdGUgKnN0YXRl
LCBpbnQxNiB0eXBlLCBpbnQzMiBwYXlsb2FkKQoreworCWlmIChzdGF0ZS0+bml0ZW1zID09IHN0
YXRlLT5jYXBpdGVtcykKKwl7CisJCWlmICgoc2l6ZV90KSBzdGF0ZS0+Y2FwaXRlbXMgKiAyID4g
QU5ZUVVFUllfTUFYSVRFTVMpCisJCQlQQVJTRV9GQUlMKHN0YXRlLCBFUlJDT0RFX1BST0dSQU1f
TElNSVRfRVhDRUVERUQsCisJCQkJCSAgIGVycm1zZygiYW55cXVlcnkgZXhwcmVzc2lvbiBpcyB0
b28gY29tcGxleCIpKTsKKwkJc3RhdGUtPmNhcGl0ZW1zICo9IDI7CisJCXN0YXRlLT5pdGVtcyA9
IChBbnlRdWVyeUl0ZW0gKikgcmVwYWxsb2Moc3RhdGUtPml0ZW1zLAorCQkJCQkJCQkJCQkJIHNp
emVvZihBbnlRdWVyeUl0ZW0pICoKKwkJCQkJCQkJCQkJCSBzdGF0ZS0+Y2FwaXRlbXMpOworCX0K
KwlzdGF0ZS0+aXRlbXNbc3RhdGUtPm5pdGVtc10udHlwZSA9IHR5cGU7CisJc3RhdGUtPml0ZW1z
W3N0YXRlLT5uaXRlbXNdLmxlZnQgPSAwOworCXN0YXRlLT5pdGVtc1tzdGF0ZS0+bml0ZW1zXS5w
YXlsb2FkID0gcGF5bG9hZDsKKwlzdGF0ZS0+bml0ZW1zKys7CisJcmV0dXJuIHRydWU7Cit9CisK
Ky8qCisgKiBDb25zdW1lIGEgdmFsdWUgdG9rZW4sIGFwcGVuZCBpdHMgc3RyaW5nICh3aXRoIHRl
cm1pbmF0aW5nIE5VTCkgdG8KKyAqIHN0YXRlLT5zdHJzLCBhbmQgZW1pdCBhIFZBTCBpdGVtIHdo
b3NlIHBheWxvYWQgaXMgdGhlIGJ5dGUgb2Zmc2V0IG9mIHRoZQorICogc3RyaW5nIHdpdGhpbiBz
dHJzLT5kYXRhLgorICovCitzdGF0aWMgYm9vbAorcGFyc2VfdmFsdWUoUGFyc2VyU3RhdGUgKnN0
YXRlKQoreworCWludDMyCQlvZmY7CisKKwlza2lwX3dzKHN0YXRlKTsKKworCWlmIChzdGF0ZS0+
Y3VyID49IHN0YXRlLT5lbmQpCisJCVBBUlNFX0ZBSUwoc3RhdGUsIEVSUkNPREVfU1lOVEFYX0VS
Uk9SLAorCQkJCSAgIGVycm1zZygidW5leHBlY3RlZCBlbmQgb2YgaW5wdXQgaW4gYW55cXVlcnki
KSk7CisKKwlvZmYgPSBzdGF0ZS0+c3Rycy5sZW47CisKKwlpZiAoKnN0YXRlLT5jdXIgPT0gJyIn
KQorCXsKKwkJc3RhdGUtPmN1cisrOwkJCS8qIG9wZW5pbmcgcXVvdGUgKi8KKwkJd2hpbGUgKHN0
YXRlLT5jdXIgPCBzdGF0ZS0+ZW5kICYmICpzdGF0ZS0+Y3VyICE9ICciJykKKwkJeworCQkJaWYg
KCpzdGF0ZS0+Y3VyID09ICdcXCcgJiYgc3RhdGUtPmN1ciArIDEgPCBzdGF0ZS0+ZW5kKQorCQkJ
CXN0YXRlLT5jdXIrKzsKKwkJCWFwcGVuZFN0cmluZ0luZm9DaGFyKCZzdGF0ZS0+c3RycywgKnN0
YXRlLT5jdXIpOworCQkJc3RhdGUtPmN1cisrOworCQl9CisJCWlmIChzdGF0ZS0+Y3VyID49IHN0
YXRlLT5lbmQpCisJCQlQQVJTRV9GQUlMKHN0YXRlLCBFUlJDT0RFX1NZTlRBWF9FUlJPUiwKKwkJ
CQkJICAgZXJybXNnKCJ1bnRlcm1pbmF0ZWQgcXVvdGVkIHZhbHVlIGluIGFueXF1ZXJ5IikpOwor
CQlzdGF0ZS0+Y3VyKys7CQkJLyogY2xvc2luZyBxdW90ZSAqLworCX0KKwllbHNlIGlmIChpc192
YWx1ZV9jaGFyKCpzdGF0ZS0+Y3VyKSkKKwl7CisJCXdoaWxlIChzdGF0ZS0+Y3VyIDwgc3RhdGUt
PmVuZCAmJiBpc192YWx1ZV9jaGFyKCpzdGF0ZS0+Y3VyKSkKKwkJeworCQkJYXBwZW5kU3RyaW5n
SW5mb0NoYXIoJnN0YXRlLT5zdHJzLCAqc3RhdGUtPmN1cik7CisJCQlzdGF0ZS0+Y3VyKys7CisJ
CX0KKwl9CisJZWxzZQorCQlQQVJTRV9GQUlMKHN0YXRlLCBFUlJDT0RFX1NZTlRBWF9FUlJPUiwK
KwkJCQkgICBlcnJtc2coImV4cGVjdGVkIHZhbHVlIGF0IGNoYXJhY3RlciBcIiVjXCIiLCAqc3Rh
dGUtPmN1cikpOworCisJYXBwZW5kU3RyaW5nSW5mb0NoYXIoJnN0YXRlLT5zdHJzLCAnXDAnKTsK
KwlyZXR1cm4gZW1pdF9pdGVtKHN0YXRlLCBBTllRX1ZBTCwgb2ZmKTsKK30KKworc3RhdGljIGJv
b2wKK3BhcnNlX2F0b20oUGFyc2VyU3RhdGUgKnN0YXRlKQoreworCXNraXBfd3Moc3RhdGUpOwor
CWlmIChzdGF0ZS0+Y3VyIDwgc3RhdGUtPmVuZCAmJiAqc3RhdGUtPmN1ciA9PSAnKCcpCisJewor
CQlzdGF0ZS0+Y3VyKys7CisJCWlmICghcGFyc2VfZXhwcihzdGF0ZSkpCisJCQlyZXR1cm4gZmFs
c2U7CisJCXNraXBfd3Moc3RhdGUpOworCQlpZiAoc3RhdGUtPmN1ciA+PSBzdGF0ZS0+ZW5kIHx8
ICpzdGF0ZS0+Y3VyICE9ICcpJykKKwkJCVBBUlNFX0ZBSUwoc3RhdGUsIEVSUkNPREVfU1lOVEFY
X0VSUk9SLAorCQkJCQkgICBlcnJtc2coIm1pc3NpbmcgY2xvc2luZyBwYXJlbnRoZXNpcyBpbiBh
bnlxdWVyeSIpKTsKKwkJc3RhdGUtPmN1cisrOworCQlyZXR1cm4gdHJ1ZTsKKwl9CisJcmV0dXJu
IHBhcnNlX3ZhbHVlKHN0YXRlKTsKK30KKworc3RhdGljIGJvb2wKK3BhcnNlX25vdChQYXJzZXJT
dGF0ZSAqc3RhdGUpCit7CisJc2tpcF93cyhzdGF0ZSk7CisJaWYgKHN0YXRlLT5jdXIgPCBzdGF0
ZS0+ZW5kICYmICpzdGF0ZS0+Y3VyID09ICchJykKKwl7CisJCXN0YXRlLT5jdXIrKzsKKwkJaWYg
KCFwYXJzZV9ub3Qoc3RhdGUpKQorCQkJcmV0dXJuIGZhbHNlOworCQlyZXR1cm4gZW1pdF9pdGVt
KHN0YXRlLCBBTllRX09QUiwgQU5ZUV9OT1QpOworCX0KKwlyZXR1cm4gcGFyc2VfYXRvbShzdGF0
ZSk7Cit9CisKK3N0YXRpYyBib29sCitwYXJzZV9hbmQoUGFyc2VyU3RhdGUgKnN0YXRlKQorewor
CWlmICghcGFyc2Vfbm90KHN0YXRlKSkKKwkJcmV0dXJuIGZhbHNlOworCWZvciAoOzspCisJewor
CQlza2lwX3dzKHN0YXRlKTsKKwkJaWYgKHN0YXRlLT5jdXIgPj0gc3RhdGUtPmVuZCB8fCAqc3Rh
dGUtPmN1ciAhPSAnJicpCisJCQlyZXR1cm4gdHJ1ZTsKKwkJc3RhdGUtPmN1cisrOworCQlpZiAo
IXBhcnNlX25vdChzdGF0ZSkpCisJCQlyZXR1cm4gZmFsc2U7CisJCWlmICghZW1pdF9pdGVtKHN0
YXRlLCBBTllRX09QUiwgQU5ZUV9BTkQpKQorCQkJcmV0dXJuIGZhbHNlOworCX0KK30KKworc3Rh
dGljIGJvb2wKK3BhcnNlX2V4cHIoUGFyc2VyU3RhdGUgKnN0YXRlKQoreworCWNoZWNrX3N0YWNr
X2RlcHRoKCk7CisKKwlpZiAoIXBhcnNlX2FuZChzdGF0ZSkpCisJCXJldHVybiBmYWxzZTsKKwlm
b3IgKDs7KQorCXsKKwkJc2tpcF93cyhzdGF0ZSk7CisJCWlmIChzdGF0ZS0+Y3VyID49IHN0YXRl
LT5lbmQgfHwgKnN0YXRlLT5jdXIgIT0gJ3wnKQorCQkJcmV0dXJuIHRydWU7CisJCXN0YXRlLT5j
dXIrKzsKKwkJaWYgKCFwYXJzZV9hbmQoc3RhdGUpKQorCQkJcmV0dXJuIGZhbHNlOworCQlpZiAo
IWVtaXRfaXRlbShzdGF0ZSwgQU5ZUV9PUFIsIEFOWVFfT1IpKQorCQkJcmV0dXJuIGZhbHNlOwor
CX0KK30KKworLyoKKyAqIENvbXB1dGUgdGhlICJsZWZ0IiBmaWVsZCBmb3IgZXZlcnkgT1BSIGl0
ZW0gYnkgd2Fsa2luZyB0aGUgcG9zdGZpeCBhcnJheQorICogdG9wLWRvd24uICBSZXR1cm5zIGZh
bHNlIG9uIG92ZXJmbG93IG9mIHRoZSBpbnQxNiBsZWZ0IGZpZWxkLgorICovCitzdGF0aWMgYm9v
bAorY29tcHV0ZV9sZWZ0cyhQYXJzZXJTdGF0ZSAqc3RhdGUsIGludCAqcG9zKQoreworCWludAkJ
CW15cG9zOworCisJY2hlY2tfc3RhY2tfZGVwdGgoKTsKKworCW15cG9zID0gKCpwb3MpLS07CisJ
QXNzZXJ0KG15cG9zID49IDApOworCisJaWYgKHN0YXRlLT5pdGVtc1tteXBvc10udHlwZSA9PSBB
TllRX1ZBTCkKKwl7CisJCXN0YXRlLT5pdGVtc1tteXBvc10ubGVmdCA9IDA7CisJCXJldHVybiB0
cnVlOworCX0KKwllbHNlIGlmIChzdGF0ZS0+aXRlbXNbbXlwb3NdLnBheWxvYWQgPT0gQU5ZUV9O
T1QpCisJeworCQlzdGF0ZS0+aXRlbXNbbXlwb3NdLmxlZnQgPSAtMTsKKwkJcmV0dXJuIGNvbXB1
dGVfbGVmdHMoc3RhdGUsIHBvcyk7CisJfQorCWVsc2UKKwl7CisJCWludAkJCWRlbHRhOworCisJ
CS8qIGJpbmFyeSBvcGVyYXRvcjogd2FsayByaWdodCBvcGVyYW5kICovCisJCWlmICghY29tcHV0
ZV9sZWZ0cyhzdGF0ZSwgcG9zKSkKKwkJCXJldHVybiBmYWxzZTsKKwkJZGVsdGEgPSAqcG9zIC0g
bXlwb3M7CisJCWlmIChkZWx0YSA8IFBHX0lOVDE2X01JTikKKwkJeworCQkJZXJyc2F2ZShzdGF0
ZS0+ZXNjb250ZXh0LAorCQkJCQkoZXJyY29kZShFUlJDT0RFX1BST0dSQU1fTElNSVRfRVhDRUVE
RUQpLAorCQkJCQkgZXJybXNnKCJhbnlxdWVyeSBleHByZXNzaW9uIGlzIHRvbyBjb21wbGV4Iikp
KTsKKwkJCXJldHVybiBmYWxzZTsKKwkJfQorCQlzdGF0ZS0+aXRlbXNbbXlwb3NdLmxlZnQgPSAo
aW50MTYpIGRlbHRhOworCQlyZXR1cm4gY29tcHV0ZV9sZWZ0cyhzdGF0ZSwgcG9zKTsKKwl9Cit9
CisKKworLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCisgKiAgSW5wdXQgLyBvdXRwdXQgLyBkZWJ1ZworICog
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tCisgKi8KKworRGF0dW0KK2FueXF1ZXJ5X2luKFBHX0ZVTkNUSU9OX0FS
R1MpCit7CisJY2hhcgkgICAqYnVmID0gUEdfR0VUQVJHX0NTVFJJTkcoMCk7CisJUGFyc2VyU3Rh
dGUgc3RhdGU7CisJQW55UXVlcnkgICAqb3V0OworCVNpemUJCWl0ZW1zX2J5dGVzOworCVNpemUJ
CXRvdGFsOworCWludAkJCXBvczsKKworCXN0YXRlLmN1ciA9IGJ1ZjsKKwlzdGF0ZS5lbmQgPSBi
dWYgKyBzdHJsZW4oYnVmKTsKKwlzdGF0ZS5jYXBpdGVtcyA9IDE2OworCXN0YXRlLml0ZW1zID0g
KEFueVF1ZXJ5SXRlbSAqKSBwYWxsb2Moc2l6ZW9mKEFueVF1ZXJ5SXRlbSkgKgorCQkJCQkJCQkJ
CSAgc3RhdGUuY2FwaXRlbXMpOworCXN0YXRlLm5pdGVtcyA9IDA7CisJaW5pdFN0cmluZ0luZm8o
JnN0YXRlLnN0cnMpOworCXN0YXRlLmVzY29udGV4dCA9IGZjaW5mby0+Y29udGV4dDsKKworCWlm
ICghcGFyc2VfZXhwcigmc3RhdGUpKQorCQlQR19SRVRVUk5fTlVMTCgpOworCisJc2tpcF93cygm
c3RhdGUpOworCWlmIChzdGF0ZS5jdXIgPCBzdGF0ZS5lbmQpCisJCWVyZXR1cm4oc3RhdGUuZXNj
b250ZXh0LCAoRGF0dW0pIDAsCisJCQkJKGVycmNvZGUoRVJSQ09ERV9TWU5UQVhfRVJST1IpLAor
CQkJCSBlcnJtc2coInVuZXhwZWN0ZWQgdHJhaWxpbmcgaW5wdXQgaW4gYW55cXVlcnkiKSkpOwor
CisJaWYgKHN0YXRlLm5pdGVtcyA9PSAwKQorCQllcmV0dXJuKHN0YXRlLmVzY29udGV4dCwgKERh
dHVtKSAwLAorCQkJCShlcnJjb2RlKEVSUkNPREVfSU5WQUxJRF9QQVJBTUVURVJfVkFMVUUpLAor
CQkJCSBlcnJtc2coImVtcHR5IGFueXF1ZXJ5IikpKTsKKworCWlmICgoc2l6ZV90KSBzdGF0ZS5u
aXRlbXMgPiBBTllRVUVSWV9NQVhJVEVNUykKKwkJZXJldHVybihzdGF0ZS5lc2NvbnRleHQsIChE
YXR1bSkgMCwKKwkJCQkoZXJyY29kZShFUlJDT0RFX1BST0dSQU1fTElNSVRfRVhDRUVERUQpLAor
CQkJCSBlcnJtc2coImFueXF1ZXJ5IGhhcyB0b28gbWFueSBpdGVtcyAoJWQsIG1heGltdW0gJXp1
KSIsCisJCQkJCQlzdGF0ZS5uaXRlbXMsIEFOWVFVRVJZX01BWElURU1TKSkpOworCisJcG9zID0g
c3RhdGUubml0ZW1zIC0gMTsKKwlpZiAoIWNvbXB1dGVfbGVmdHMoJnN0YXRlLCAmcG9zKSkKKwkJ
UEdfUkVUVVJOX05VTEwoKTsKKwlBc3NlcnQocG9zID09IC0xKTsKKworCWl0ZW1zX2J5dGVzID0g
TUFYQUxJR04oc3RhdGUubml0ZW1zICogc2l6ZW9mKEFueVF1ZXJ5SXRlbSkpOworCXRvdGFsID0g
QU5ZUVVFUllfSERSU0laRSArIGl0ZW1zX2J5dGVzICsgc3RhdGUuc3Rycy5sZW47CisKKwlvdXQg
PSAoQW55UXVlcnkgKikgcGFsbG9jMCh0b3RhbCk7CisJU0VUX1ZBUlNJWkUob3V0LCB0b3RhbCk7
CisJb3V0LT5zaXplID0gc3RhdGUubml0ZW1zOworCW91dC0+c3RyX29mZiA9IEFOWVFVRVJZX0hE
UlNJWkUgKyBpdGVtc19ieXRlczsKKwlvdXQtPnN0cl9sZW4gPSBzdGF0ZS5zdHJzLmxlbjsKKwlt
ZW1jcHkob3V0LT5pdGVtcywgc3RhdGUuaXRlbXMsIHN0YXRlLm5pdGVtcyAqIHNpemVvZihBbnlR
dWVyeUl0ZW0pKTsKKwltZW1jcHkoKGNoYXIgKikgb3V0ICsgb3V0LT5zdHJfb2ZmLCBzdGF0ZS5z
dHJzLmRhdGEsIHN0YXRlLnN0cnMubGVuKTsKKworCXBmcmVlKHN0YXRlLml0ZW1zKTsKKwlwZnJl
ZShzdGF0ZS5zdHJzLmRhdGEpOworCisJUEdfUkVUVVJOX1BPSU5URVIob3V0KTsKK30KKworLyoK
KyAqIFF1b3RlIGEgdmFsdWUgc3RyaW5nIGlmIGl0IGNvbnRhaW5zIGFueXRoaW5nIHRoZSBwYXJz
ZXIgd291bGQgY29uc2lkZXIKKyAqIHNwZWNpYWwuICBPdGhlcndpc2UgZW1pdCBpdCB2ZXJiYXRp
bS4KKyAqLworc3RhdGljIHZvaWQKK2FwcGVuZF92YWx1ZV90b2tlbihTdHJpbmdJbmZvIG91dCwg
Y29uc3QgY2hhciAqcykKK3sKKwljb25zdCBjaGFyICpwOworCWJvb2wJCW5lZWRfcXVvdGUgPSAo
KnMgPT0gJ1wwJyk7CisKKwlmb3IgKHAgPSBzOyAqcDsgcCsrKQorCXsKKwkJaWYgKCFpc192YWx1
ZV9jaGFyKCpwKSkKKwkJeworCQkJbmVlZF9xdW90ZSA9IHRydWU7CisJCQlicmVhazsKKwkJfQor
CX0KKworCWlmICghbmVlZF9xdW90ZSkKKwl7CisJCWFwcGVuZFN0cmluZ0luZm9TdHJpbmcob3V0
LCBzKTsKKwkJcmV0dXJuOworCX0KKworCWFwcGVuZFN0cmluZ0luZm9DaGFyKG91dCwgJyInKTsK
Kwlmb3IgKHAgPSBzOyAqcDsgcCsrKQorCXsKKwkJaWYgKCpwID09ICciJyB8fCAqcCA9PSAnXFwn
KQorCQkJYXBwZW5kU3RyaW5nSW5mb0NoYXIob3V0LCAnXFwnKTsKKwkJYXBwZW5kU3RyaW5nSW5m
b0NoYXIob3V0LCAqcCk7CisJfQorCWFwcGVuZFN0cmluZ0luZm9DaGFyKG91dCwgJyInKTsKK30K
KworLyoKKyAqIEluZml4IHdhbGtlciBmb3IgdGhlIG91dHB1dCBmdW5jdGlvbi4gIFJldHVybnMg
dGhlIHBvc3RmaXggaW5kZXggdGhhdAorICogImN1ciIgZGVjcmVtZW50ZWQgdG8gc28gdGhlIGNh
bGxlciBjYW4gY2hhaW4uCisgKi8KK3N0YXRpYyBpbnQKK2luZml4X3dhbGsoU3RyaW5nSW5mbyBv
dXQsIEFueVF1ZXJ5ICpxLCBpbnQgY3VyLCBib29sIHRvcCkKK3sKKwlBbnlRdWVyeUl0ZW0gKml0
OworCisJY2hlY2tfc3RhY2tfZGVwdGgoKTsKKwlBc3NlcnQoY3VyID49IDApOworCWl0ID0gJnEt
Pml0ZW1zW2N1cl07CisKKwlpZiAoaXQtPnR5cGUgPT0gQU5ZUV9WQUwpCisJeworCQlhcHBlbmRf
dmFsdWVfdG9rZW4ob3V0LCBBTllRVUVSWV9TVFJJTkcocSwgaXQpKTsKKwkJcmV0dXJuIGN1ciAt
IDE7CisJfQorCWVsc2UgaWYgKGl0LT5wYXlsb2FkID09IEFOWVFfTk9UKQorCXsKKwkJQW55UXVl
cnlJdGVtICpjaGlsZCA9ICZxLT5pdGVtc1tjdXIgLSAxXTsKKwkJYm9vbAkJcGFyZW4gPSAoY2hp
bGQtPnR5cGUgPT0gQU5ZUV9PUFIpOworCisJCWFwcGVuZFN0cmluZ0luZm9DaGFyKG91dCwgJyEn
KTsKKwkJaWYgKHBhcmVuKQorCQkJYXBwZW5kU3RyaW5nSW5mb1N0cmluZyhvdXQsICIoICIpOwor
CQljdXIgPSBpbmZpeF93YWxrKG91dCwgcSwgY3VyIC0gMSwgZmFsc2UpOworCQlpZiAocGFyZW4p
CisJCQlhcHBlbmRTdHJpbmdJbmZvU3RyaW5nKG91dCwgIiApIik7CisJCXJldHVybiBjdXI7CisJ
fQorCWVsc2UKKwl7CisJCWludAkJCW9wID0gaXQtPnBheWxvYWQ7CisJCVN0cmluZ0luZm9EYXRh
IHJpZ2h0OworCQlpbnQJCQluZXh0OworCisJCWlmIChvcCA9PSBBTllRX09SICYmICF0b3ApCisJ
CQlhcHBlbmRTdHJpbmdJbmZvU3RyaW5nKG91dCwgIiggIik7CisKKwkJLyogcmlnaHQgb3BlcmFu
ZCBmaXJzdCBpbnRvIGEgc2lkZSBidWZmZXIgKi8KKwkJaW5pdFN0cmluZ0luZm8oJnJpZ2h0KTsK
KwkJbmV4dCA9IGluZml4X3dhbGsoJnJpZ2h0LCBxLCBjdXIgLSAxLCBmYWxzZSk7CisJCS8qIGxl
ZnQgb3BlcmFuZCBpbnRvIHRoZSBtYWluIGJ1ZmZlciAqLworCQljdXIgPSBpbmZpeF93YWxrKG91
dCwgcSwgbmV4dCwgZmFsc2UpOworCisJCWFwcGVuZFN0cmluZ0luZm8ob3V0LCAiICVjICVzIiwg
b3AsIHJpZ2h0LmRhdGEpOworCQlwZnJlZShyaWdodC5kYXRhKTsKKworCQlpZiAob3AgPT0gQU5Z
UV9PUiAmJiAhdG9wKQorCQkJYXBwZW5kU3RyaW5nSW5mb1N0cmluZyhvdXQsICIgKSIpOworCQly
ZXR1cm4gY3VyOworCX0KK30KKworRGF0dW0KK2FueXF1ZXJ5X291dChQR19GVU5DVElPTl9BUkdT
KQoreworCUFueVF1ZXJ5ICAgKnEgPSBQR19HRVRBUkdfQU5ZUVVFUllfUCgwKTsKKwlTdHJpbmdJ
bmZvRGF0YSBvdXQ7CisKKwlpZiAocS0+c2l6ZSA8PSAwKQorCQllcmVwb3J0KEVSUk9SLAorCQkJ
CShlcnJjb2RlKEVSUkNPREVfSU5WQUxJRF9QQVJBTUVURVJfVkFMVUUpLAorCQkJCSBlcnJtc2co
ImVtcHR5IGFueXF1ZXJ5IikpKTsKKworCWluaXRTdHJpbmdJbmZvKCZvdXQpOworCSh2b2lkKSBp
bmZpeF93YWxrKCZvdXQsIHEsIHEtPnNpemUgLSAxLCB0cnVlKTsKKworCVBHX1JFVFVSTl9DU1RS
SU5HKG91dC5kYXRhKTsKK30KKworLyoKKyAqIERlYnVnZ2luZyBoZWxwZXI6IHByb2R1Y2UgYSBw
b3N0Zml4IHN0cmluZyB3aXRoIG9wZXJhdG9yIGNvZGVzIHNwZWxsZWQgb3V0LgorICogTW9zdGx5
IHVzZWZ1bCB3aGlsZSB3cml0aW5nIHRlc3RzLgorICovCitEYXR1bQorYW55cXVlcnlfcXVlcnl0
cmVlKFBHX0ZVTkNUSU9OX0FSR1MpCit7CisJQW55UXVlcnkgICAqcSA9IFBHX0dFVEFSR19BTllR
VUVSWV9QKDApOworCVN0cmluZ0luZm9EYXRhIG91dDsKKwlpbnQJCQlpOworCisJaW5pdFN0cmlu
Z0luZm8oJm91dCk7CisJZm9yIChpID0gMDsgaSA8IHEtPnNpemU7IGkrKykKKwl7CisJCUFueVF1
ZXJ5SXRlbSAqaXQgPSAmcS0+aXRlbXNbaV07CisKKwkJaWYgKGkgPiAwKQorCQkJYXBwZW5kU3Ry
aW5nSW5mb0NoYXIoJm91dCwgJyAnKTsKKwkJaWYgKGl0LT50eXBlID09IEFOWVFfVkFMKQorCQkJ
YXBwZW5kX3ZhbHVlX3Rva2VuKCZvdXQsIEFOWVFVRVJZX1NUUklORyhxLCBpdCkpOworCQllbHNl
CisJCQlhcHBlbmRTdHJpbmdJbmZvQ2hhcigmb3V0LCAoY2hhcikgaXQtPnBheWxvYWQpOworCX0K
KwlQR19SRVRVUk5fVEVYVF9QKGNzdHJpbmdfdG9fdGV4dF93aXRoX2xlbihvdXQuZGF0YSwgb3V0
LmxlbikpOworfQorCisKKy8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQorICogIE1hdGNoaW5nOiBhbnlhcnJh
eSBAQCBhbnlxdWVyeQorICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCisgKi8KKwordHlwZWRlZiBzdHJ1Y3Qg
TWF0Y2hDb250ZXh0Cit7CisJQW55QXJyYXlUeXBlSW5mbyAqbWV0YTsKKwlEYXR1bQkgICAqc29y
dGVkOwkJCS8qIHNvcnRlZCBhcnJheSBlbGVtZW50cyAob3duZWQpICovCisJaW50CQkJbmVsZW1z
OworCS8qIGNhY2hlZCBwYXJzZWQgdmFsdWVzIGZvciBlYWNoIFZBTCBpdGVtIGluIHRoZSBxdWVy
eSAqLworCURhdHVtCSAgICpwYXJzZWQ7CisJYm9vbAkgICAqcGFyc2VkX3ZhbGlkOworfSBNYXRj
aENvbnRleHQ7CisKKy8qCisgKiBMb29rIHVwIHZhbCBpbiB0aGUgc29ydGVkIGVsZW1lbnQgYXJy
YXkgdmlhIGJpbmFyeSBzZWFyY2guCisgKi8KK3N0YXRpYyBib29sCitjb250YWluc192YWx1ZShN
YXRjaENvbnRleHQgKmN0eCwgRGF0dW0gdmFsKQoreworCWludAkJCWxvID0gMDsKKwlpbnQJCQlo
aSA9IGN0eC0+bmVsZW1zOworCisJd2hpbGUgKGxvIDwgaGkpCisJeworCQlpbnQJCQltaWQgPSBs
byArIChoaSAtIGxvKSAvIDI7CisJCWludAkJCWMgPSBEYXR1bUdldEludDMyKEZ1bmN0aW9uQ2Fs
bDJDb2xsKCZjdHgtPm1ldGEtPmNtcF9wcm9jLAorCQkJCQkJCQkJCQkJCQljdHgtPm1ldGEtPnR5
cGNvbGxhdGlvbiwKKwkJCQkJCQkJCQkJCQkJY3R4LT5zb3J0ZWRbbWlkXSwKKwkJCQkJCQkJCQkJ
CQkJdmFsKSk7CisKKwkJaWYgKGMgPT0gMCkKKwkJCXJldHVybiB0cnVlOworCQlpZiAoYyA8IDAp
CisJCQlsbyA9IG1pZCArIDE7CisJCWVsc2UKKwkJCWhpID0gbWlkOworCX0KKwlyZXR1cm4gZmFs
c2U7Cit9CisKKy8qCisgKiBFdmFsdWF0ZSBvbmUgbm9kZSBvZiB0aGUgcG9zdGZpeCB0cmVlLiAg
UmVjdXJzaXZlIG9uIG9wZXJhdG9ycy4KKyAqLworc3RhdGljIGJvb2wKK2V2YWxfaXRlbShBbnlR
dWVyeSAqcSwgaW50IGlkeCwgTWF0Y2hDb250ZXh0ICpjdHgsIE9pZCBpbnB1dF9mdW5jLAorCQkg
IGludCBpbnB1dF90eXBpb3BhcmFtLCBpbnQzMiBpbnB1dF90eXBtb2QpCit7CisJQW55UXVlcnlJ
dGVtICppdDsKKworCWNoZWNrX3N0YWNrX2RlcHRoKCk7CisJQXNzZXJ0KGlkeCA+PSAwKTsKKwlp
dCA9ICZxLT5pdGVtc1tpZHhdOworCisJaWYgKGl0LT50eXBlID09IEFOWVFfVkFMKQorCXsKKwkJ
RGF0dW0JCXY7CisKKwkJaWYgKCFjdHgtPnBhcnNlZF92YWxpZFtpZHhdKQorCQl7CisJCQljb25z
dCBjaGFyICpzID0gQU5ZUVVFUllfU1RSSU5HKHEsIGl0KTsKKworCQkJdiA9IE9pZElucHV0RnVu
Y3Rpb25DYWxsKGlucHV0X2Z1bmMsIChjaGFyICopIHMsCisJCQkJCQkJCQkgaW5wdXRfdHlwaW9w
YXJhbSwgaW5wdXRfdHlwbW9kKTsKKwkJCWN0eC0+cGFyc2VkW2lkeF0gPSB2OworCQkJY3R4LT5w
YXJzZWRfdmFsaWRbaWR4XSA9IHRydWU7CisJCX0KKwkJcmV0dXJuIGNvbnRhaW5zX3ZhbHVlKGN0
eCwgY3R4LT5wYXJzZWRbaWR4XSk7CisJfQorCWVsc2UgaWYgKGl0LT5wYXlsb2FkID09IEFOWVFf
Tk9UKQorCXsKKwkJcmV0dXJuICFldmFsX2l0ZW0ocSwgaWR4IC0gMSwgY3R4LCBpbnB1dF9mdW5j
LAorCQkJCQkJICBpbnB1dF90eXBpb3BhcmFtLCBpbnB1dF90eXBtb2QpOworCX0KKwllbHNlIGlm
IChpdC0+cGF5bG9hZCA9PSBBTllRX0FORCkKKwl7CisJCWlmICghZXZhbF9pdGVtKHEsIGlkeCAr
IGl0LT5sZWZ0LCBjdHgsIGlucHV0X2Z1bmMsCisJCQkJCSAgIGlucHV0X3R5cGlvcGFyYW0sIGlu
cHV0X3R5cG1vZCkpCisJCQlyZXR1cm4gZmFsc2U7CisJCXJldHVybiBldmFsX2l0ZW0ocSwgaWR4
IC0gMSwgY3R4LCBpbnB1dF9mdW5jLAorCQkJCQkJIGlucHV0X3R5cGlvcGFyYW0sIGlucHV0X3R5
cG1vZCk7CisJfQorCWVsc2UJCQkJCQkvKiBBTllRX09SICovCisJeworCQlpZiAoZXZhbF9pdGVt
KHEsIGlkeCArIGl0LT5sZWZ0LCBjdHgsIGlucHV0X2Z1bmMsCisJCQkJCSAgaW5wdXRfdHlwaW9w
YXJhbSwgaW5wdXRfdHlwbW9kKSkKKwkJCXJldHVybiB0cnVlOworCQlyZXR1cm4gZXZhbF9pdGVt
KHEsIGlkeCAtIDEsIGN0eCwgaW5wdXRfZnVuYywKKwkJCQkJCSBpbnB1dF90eXBpb3BhcmFtLCBp
bnB1dF90eXBtb2QpOworCX0KK30KKworc3RhdGljIERhdHVtCitkb19ib29sb3AoRnVuY3Rpb25D
YWxsSW5mbyBmY2luZm8sIEFycmF5VHlwZSAqYXJyLCBBbnlRdWVyeSAqcSkKK3sKKwlBbnlBcnJh
eVR5cGVJbmZvICptZXRhOworCURhdHVtCSAgICp2YWx1ZXM7CisJYm9vbAkgICAqbnVsbHM7CisJ
aW50CQkJbmVsZW1zOworCU9pZAkJCWlucHV0X2Z1bmM7CisJT2lkCQkJaW5wdXRfdHlwaW9wYXJh
bTsKKwlib29sCQlyZXN1bHQ7CisJTWF0Y2hDb250ZXh0IGN0eDsKKworCUFOWUFSUkFZX0NIRUNL
X0FSUkFZKGFycik7CisKKwlpZiAocS0+c2l6ZSA8PSAwKQorCQllcmVwb3J0KEVSUk9SLAorCQkJ
CShlcnJjb2RlKEVSUkNPREVfSU5WQUxJRF9QQVJBTUVURVJfVkFMVUUpLAorCQkJCSBlcnJtc2co
ImVtcHR5IGFueXF1ZXJ5IikpKTsKKworCW1ldGEgPSBhbnlhcnJheV9nZXRfbWV0YShmY2luZm8s
IEFSUl9FTEVNVFlQRShhcnIpLCBmYWxzZSk7CisKKwlpZiAoQVJSX05ESU0oYXJyKSA9PSAwKQor
CXsKKwkJbmVsZW1zID0gMDsKKwkJdmFsdWVzID0gTlVMTDsKKwl9CisJZWxzZQorCXsKKwkJZGVj
b25zdHJ1Y3RfYXJyYXkoYXJyLCBtZXRhLT5lbGVtZW50X3R5cGUsIG1ldGEtPnR5cGxlbiwKKwkJ
CQkJCSAgbWV0YS0+dHlwYnl2YWwsIG1ldGEtPnR5cGFsaWduLAorCQkJCQkJICAmdmFsdWVzLCAm
bnVsbHMsICZuZWxlbXMpOworCQlwZnJlZShudWxscyk7CisJCWlmIChuZWxlbXMgPiAxKQorCQkJ
cXNvcnRfYXJnKHZhbHVlcywgbmVsZW1zLCBzaXplb2YoRGF0dW0pLAorCQkJCQkgIGFueWFycmF5
X2NtcF9kYXR1bSwgbWV0YSk7CisJfQorCisJZ2V0VHlwZUlucHV0SW5mbyhtZXRhLT5lbGVtZW50
X3R5cGUsICZpbnB1dF9mdW5jLCAmaW5wdXRfdHlwaW9wYXJhbSk7CisKKwljdHgubWV0YSA9IG1l
dGE7CisJY3R4LnNvcnRlZCA9IHZhbHVlczsKKwljdHgubmVsZW1zID0gbmVsZW1zOworCWN0eC5w
YXJzZWQgPSAoRGF0dW0gKikgcGFsbG9jMChzaXplb2YoRGF0dW0pICogcS0+c2l6ZSk7CisJY3R4
LnBhcnNlZF92YWxpZCA9IChib29sICopIHBhbGxvYzAoc2l6ZW9mKGJvb2wpICogcS0+c2l6ZSk7
CisKKwlyZXN1bHQgPSBldmFsX2l0ZW0ocSwgcS0+c2l6ZSAtIDEsICZjdHgsIGlucHV0X2Z1bmMs
CisJCQkJCSAgIGlucHV0X3R5cGlvcGFyYW0sIC0xKTsKKworCXBmcmVlKGN0eC5wYXJzZWQpOwor
CXBmcmVlKGN0eC5wYXJzZWRfdmFsaWQpOworCWlmICh2YWx1ZXMpCisJCXBmcmVlKHZhbHVlcyk7
CisKKwlQR19SRVRVUk5fQk9PTChyZXN1bHQpOworfQorCitEYXR1bQorYW55YXJyYXlfYm9vbG9w
KFBHX0ZVTkNUSU9OX0FSR1MpCit7CisJQXJyYXlUeXBlICAqYXJyID0gUEdfR0VUQVJHX0FSUkFZ
VFlQRV9QKDApOworCUFueVF1ZXJ5ICAgKnEgPSBQR19HRVRBUkdfQU5ZUVVFUllfUCgxKTsKKwlE
YXR1bQkJcmVzdWx0ID0gZG9fYm9vbG9wKGZjaW5mbywgYXJyLCBxKTsKKworCVBHX0ZSRUVfSUZf
Q09QWShhcnIsIDApOworCVBHX0ZSRUVfSUZfQ09QWShxLCAxKTsKKwlyZXR1cm4gcmVzdWx0Owor
fQorCisvKgorICogQ29tbXV0YXRvcjogYW55cXVlcnkgfn4gYW55YXJyYXkgc2ltcGx5IHN3YXBz
IHRoZSBhcmd1bWVudHMuCisgKi8KK0RhdHVtCithbnlxdWVyeV9ib29sb3BfcmV2KFBHX0ZVTkNU
SU9OX0FSR1MpCit7CisJQW55UXVlcnkgICAqcSA9IFBHX0dFVEFSR19BTllRVUVSWV9QKDApOwor
CUFycmF5VHlwZSAgKmFyciA9IFBHX0dFVEFSR19BUlJBWVRZUEVfUCgxKTsKKwlEYXR1bQkJcmVz
dWx0ID0gZG9fYm9vbG9wKGZjaW5mbywgYXJyLCBxKTsKKworCVBHX0ZSRUVfSUZfQ09QWShxLCAw
KTsKKwlQR19GUkVFX0lGX0NPUFkoYXJyLCAxKTsKKwlyZXR1cm4gcmVzdWx0OworfQpkaWZmIC0t
Z2l0IGEvY29udHJpYi9hbnlhcnJheS9hbnlhcnJheV9naW4uYyBiL2NvbnRyaWIvYW55YXJyYXkv
YW55YXJyYXlfZ2luLmMKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAuLmQ5
ZDIwMWMxMmQ1Ci0tLSAvZGV2L251bGwKKysrIGIvY29udHJpYi9hbnlhcnJheS9hbnlhcnJheV9n
aW4uYwpAQCAtMCwwICsxLDM3NCBAQAorLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCisgKgorICogYW55YXJy
YXlfZ2luLmMKKyAqCQlHSU4gb3BjbGFzc2VzIHRoYXQgYWRkIHRoZSBAQCAoYW55YXJyYXksIGFu
eXF1ZXJ5KSBib29sZWFuIHNlYXJjaAorICoJCW9wZXJhdG9yIHRvIHRoZSBleGlzdGluZyBhcnJh
eV9vcHMgYmVoYXZpb3VyLgorICoKKyAqIEdJTidzIGV4dHJhY3RRdWVyeSBzdXBwb3J0IGZ1bmN0
aW9uIGRvZXNuJ3Qgc2VlIGZuX2V4cHIsIHNvIHRoZSBlbGVtZW50CisgKiB0eXBlIGNhbm5vdCBi
ZSBkZXJpdmVkIGR5bmFtaWNhbGx5IHdoZW4gdGhlIHF1ZXJ5IGlzIGFuIGFueXF1ZXJ5ICh3aGlj
aAorICogY2FycmllcyBvbmx5IHRleHQgdG9rZW5zKS4gIFdlIHdvcmsgYXJvdW5kIHRoaXMgYnkg
ZXhwb3Npbmcgb25lIG9wY2xhc3MKKyAqIHBlciBjb25jcmV0ZSBlbGVtZW50IHR5cGU7IGVhY2gg
aXMgYSB0aGluIEMgd3JhcHBlciB0aGF0IGRpc3BhdGNoZXMgb24KKyAqIHRoZSBzdHJhdGVneSBu
dW1iZXIsIGRlbGVnYXRpbmcgc3RhbmRhcmQgb3BlcmF0b3JzIHRvIGlubGluZSByZXBsaWNhcyBv
ZgorICogY29yZSdzIGFycmF5X29wcyBiZWhhdmlvdXIgYW5kIHBhcnNpbmcgYW55cXVlcnkgdG9r
ZW5zIHZpYSB0aGUgdHlwZSdzCisgKiBpbnB1dCBmdW5jdGlvbiBmb3Igc3RyYXRlZ3kgNS4KKyAq
CisgKiBDb3B5cmlnaHQgKGMpIDIwMjYsIFBvc3RncmVTUUwgR2xvYmFsIERldmVsb3BtZW50IEdy
b3VwCisgKgorICogSURFTlRJRklDQVRJT04KKyAqCQljb250cmliL2FueWFycmF5L2FueWFycmF5
X2dpbi5jCisgKgorICotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCisgKi8KKworI2luY2x1ZGUgInBvc3RncmVz
LmgiCisKKyNpbmNsdWRlICJhbnlhcnJheS5oIgorCisjaW5jbHVkZSAiYWNjZXNzL2dpbi5oIgor
I2luY2x1ZGUgImFjY2Vzcy9zdHJhdG51bS5oIgorI2luY2x1ZGUgImNhdGFsb2cvcGdfdHlwZS5o
IgorI2luY2x1ZGUgInV0aWxzL2FycmF5LmgiCisjaW5jbHVkZSAidXRpbHMvYnVpbHRpbnMuaCIK
KyNpbmNsdWRlICJ1dGlscy9sc3lzY2FjaGUuaCIKKworUEdfRlVOQ1RJT05fSU5GT19WMShhbnlh
cnJheV9naW5fZXh0cmFjdF9xdWVyeV9pbnQ4KTsKK1BHX0ZVTkNUSU9OX0lORk9fVjEoYW55YXJy
YXlfZ2luX2V4dHJhY3RfcXVlcnlfdXVpZCk7CitQR19GVU5DVElPTl9JTkZPX1YxKGFueWFycmF5
X2dpbl9leHRyYWN0X3F1ZXJ5X3RleHQpOworUEdfRlVOQ1RJT05fSU5GT19WMShhbnlhcnJheV9n
aW5fY29uc2lzdGVudF9pbnQ4KTsKK1BHX0ZVTkNUSU9OX0lORk9fVjEoYW55YXJyYXlfZ2luX2Nv
bnNpc3RlbnRfdXVpZCk7CitQR19GVU5DVElPTl9JTkZPX1YxKGFueWFycmF5X2dpbl9jb25zaXN0
ZW50X3RleHQpOworCisKKy8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQorICogIENvbW1vbjogZXh0cmFjdFF1
ZXJ5IGRpc3BhdGNoZXIKKyAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQorICovCisKKy8qCisgKiBFeHRyYWN0
IGFycmF5IGVsZW1lbnRzIGFzIEdJTiBrZXlzICh1c2VkIGZvciBzdHJhdGVnaWVzIDEtNCkuCisg
KgorICogTWlycm9ycyBjb3JlJ3MgZ2lucXVlcnlhcnJheWV4dHJhY3QgbG9naWMsIGJ1dCBpbmxp
bmVkIHNvIHdlIGRvbid0IGRlcGVuZAorICogb24gaXQgYmVpbmcgY2FsbGFibGUuICBSZXR1cm5z
IGEgZnJlc2hseS1wYWxsb2MnZCBEYXR1bSB2ZWN0b3IuCisgKi8KK3N0YXRpYyBEYXR1bSAqCitl
eHRyYWN0X2FycmF5X2tleXMoQXJyYXlUeXBlICphcnIsIEFueUFycmF5VHlwZUluZm8gKm1ldGEs
CisJCQkJICAgaW50MzIgKm5lbnRyaWVzLCBib29sICoqbnVsbHNfb3V0KQoreworCURhdHVtCSAg
ICp2YWx1ZXM7CisJYm9vbAkgICAqbnVsbHM7CisJaW50CQkJbjsKKwlpbnQJCQlpOworCWludAkJ
CWogPSAwOworCisJaWYgKEFSUl9ORElNKGFycikgPT0gMCkKKwl7CisJCSpuZW50cmllcyA9IDA7
CisJCSpudWxsc19vdXQgPSBOVUxMOworCQlyZXR1cm4gTlVMTDsKKwl9CisKKwlkZWNvbnN0cnVj
dF9hcnJheShhcnIsIG1ldGEtPmVsZW1lbnRfdHlwZSwgbWV0YS0+dHlwbGVuLAorCQkJCQkgIG1l
dGEtPnR5cGJ5dmFsLCBtZXRhLT50eXBhbGlnbiwKKwkJCQkJICAmdmFsdWVzLCAmbnVsbHMsICZu
KTsKKworCS8qIGNvbXBhY3Qgb3V0IE5VTEwgZW50cmllcyAod2UgdHJlYXQgTlVMTHMgYXMgbmV2
ZXItcHJlc2VudCkgKi8KKwlmb3IgKGkgPSAwOyBpIDwgbjsgaSsrKQorCXsKKwkJaWYgKCFudWxs
c1tpXSkKKwkJeworCQkJaWYgKGogIT0gaSkKKwkJCXsKKwkJCQl2YWx1ZXNbal0gPSB2YWx1ZXNb
aV07CisJCQkJbnVsbHNbal0gPSBmYWxzZTsKKwkJCX0KKwkJCWorKzsKKwkJfQorCX0KKworCSpu
ZW50cmllcyA9IGo7CisJKm51bGxzX291dCA9IG51bGxzOworCXJldHVybiB2YWx1ZXM7Cit9CisK
Ky8qCisgKiBXYWxrIHRoZSBhbnlxdWVyeTogZXZlcnkgVkFMIGlzIGEga2V5IHRoYXQgbXVzdCBi
ZSBsb29rZWQgdXAgaW4gdGhlIEdJTgorICogaW5kZXguICBPcGVyYXRvcnMgKCYgfCAhKSBkbyBu
b3QgY29udHJpYnV0ZSBrZXlzLiAgUmV0dXJucyB0cnVlIGlmIGF0CisgKiBsZWFzdCBvbmUgVkFM
IG11c3QgYmUgcHJlc2VudCBmb3IgdGhlIHF1ZXJ5IHRvIHBvc3NpYmx5IG1hdGNoIChpLmUuIHRo
ZQorICogcXVlcnkgaXMgbm90IGUuZy4gIiFmb28iKS4KKyAqLworc3RhdGljIGJvb2wKK2FueXF1
ZXJ5X2hhc19yZXF1aXJlZChBbnlRdWVyeSAqcSwgaW50IGlkeCkKK3sKKwlBbnlRdWVyeUl0ZW0g
Kml0OworCisJaWYgKGlkeCA8IDApCisJCXJldHVybiBmYWxzZTsKKwlpdCA9ICZxLT5pdGVtc1tp
ZHhdOworCisJaWYgKGl0LT50eXBlID09IEFOWVFfVkFMKQorCQlyZXR1cm4gdHJ1ZTsKKwlpZiAo
aXQtPnBheWxvYWQgPT0gQU5ZUV9OT1QpCisJCXJldHVybiBmYWxzZTsJCQkvKiBhc3N1bWUgbm9u
LXJlcXVpcmVkIHVuZGVyIE5PVCAqLworCWlmIChpdC0+cGF5bG9hZCA9PSBBTllRX0FORCkKKwkJ
cmV0dXJuIGFueXF1ZXJ5X2hhc19yZXF1aXJlZChxLCBpZHggKyBpdC0+bGVmdCkgfHwKKwkJCWFu
eXF1ZXJ5X2hhc19yZXF1aXJlZChxLCBpZHggLSAxKTsKKwkvKiBPUjogYm90aCBzaWRlcyBtdXN0
IGNvbnRhaW4gcmVxdWlyZWQgdmFsdWVzICovCisJcmV0dXJuIGFueXF1ZXJ5X2hhc19yZXF1aXJl
ZChxLCBpZHggKyBpdC0+bGVmdCkgJiYKKwkJYW55cXVlcnlfaGFzX3JlcXVpcmVkKHEsIGlkeCAt
IDEpOworfQorCitzdGF0aWMgRGF0dW0KK2RvX2dpbl9leHRyYWN0X3F1ZXJ5KEZ1bmN0aW9uQ2Fs
bEluZm8gZmNpbmZvLCBPaWQgZWxlbV90eXBlKQoreworCURhdHVtCQlxdWVyeURhdHVtID0gUEdf
R0VUQVJHX0RBVFVNKDApOworCWludDMyCSAgICpuZW50cmllcyA9IChpbnQzMiAqKSBQR19HRVRB
UkdfUE9JTlRFUigxKTsKKwlTdHJhdGVneU51bWJlciBzdHJhdCA9IFBHX0dFVEFSR19VSU5UMTYo
Mik7CisKKwkvKiBQR19HRVRBUkdfUE9JTlRFUigzKTogcGFydGlhbF9tYXRjaGVzIC0tIG5vdCB1
c2VkICovCisJLyogUEdfR0VUQVJHX1BPSU5URVIoNCk6IGV4dHJhX2RhdGEgLS0gbm90IHVzZWQg
Ki8KKwlib29sCSAgKipudWxsRmxhZ3MgPSAoYm9vbCAqKikgUEdfR0VUQVJHX1BPSU5URVIoNSk7
CisJaW50MzIJICAgKnNlYXJjaE1vZGUgPSAoaW50MzIgKikgUEdfR0VUQVJHX1BPSU5URVIoNik7
CisJRGF0dW0JICAgKmtleXMgPSBOVUxMOworCisJKm5lbnRyaWVzID0gMDsKKwkqbnVsbEZsYWdz
ID0gTlVMTDsKKwkqc2VhcmNoTW9kZSA9IEdJTl9TRUFSQ0hfTU9ERV9ERUZBVUxUOworCisJaWYg
KHN0cmF0ID09IEFOWUFSUkFZX0dJTl9CT09MRUFOX1NUUkFURUdZKQorCXsKKwkJQW55UXVlcnkg
ICAqcSA9IERhdHVtR2V0QW55UXVlcnlQKHF1ZXJ5RGF0dW0pOworCQlPaWQJCQlpbnB1dF9mdW5j
OworCQlPaWQJCQlpbnB1dF90eXBpb3BhcmFtOworCQlpbnQJCQlpOworCQlpbnQJCQlrID0gMDsK
KworCQlpZiAocS0+c2l6ZSA8PSAwKQorCQkJUEdfUkVUVVJOX1BPSU5URVIoTlVMTCk7CisKKwkJ
LyoKKwkJICogSWYgdGhlIHF1ZXJ5IGhhcyBubyByZXF1aXJlZCBWQUwgKGUuZy4ganVzdCAiIWZv
byIpLCB3ZSBtdXN0IHNjYW4KKwkJICogdGhlIHdob2xlIGluZGV4IGJlY2F1c2Ugcm93cyBjb250
YWluaW5nIE5PTkUgb2YgdGhlIHF1ZXJpZWQgdmFsdWVzCisJCSAqIGFyZSB2YWxpZCBtYXRjaGVz
LgorCQkgKi8KKwkJaWYgKCFhbnlxdWVyeV9oYXNfcmVxdWlyZWQocSwgcS0+c2l6ZSAtIDEpKQor
CQkJKnNlYXJjaE1vZGUgPSBHSU5fU0VBUkNIX01PREVfQUxMOworCisJCWdldFR5cGVJbnB1dElu
Zm8oZWxlbV90eXBlLCAmaW5wdXRfZnVuYywgJmlucHV0X3R5cGlvcGFyYW0pOworCQlrZXlzID0g
KERhdHVtICopIHBhbGxvYyhzaXplb2YoRGF0dW0pICogcS0+c2l6ZSk7CisKKwkJZm9yIChpID0g
MDsgaSA8IHEtPnNpemU7IGkrKykKKwkJeworCQkJQW55UXVlcnlJdGVtICppdCA9ICZxLT5pdGVt
c1tpXTsKKworCQkJaWYgKGl0LT50eXBlICE9IEFOWVFfVkFMKQorCQkJCWNvbnRpbnVlOworCQkJ
a2V5c1trKytdID0gT2lkSW5wdXRGdW5jdGlvbkNhbGwoaW5wdXRfZnVuYywKKwkJCQkJCQkJCQkJ
IChjaGFyICopIEFOWVFVRVJZX1NUUklORyhxLCBpdCksCisJCQkJCQkJCQkJCSBpbnB1dF90eXBp
b3BhcmFtLCAtMSk7CisJCX0KKwkJKm5lbnRyaWVzID0gazsKKwkJUEdfUkVUVVJOX1BPSU5URVIo
a2V5cyk7CisJfQorCWVsc2UKKwl7CisJCUFycmF5VHlwZSAgKmFyciA9IERhdHVtR2V0QXJyYXlU
eXBlUChxdWVyeURhdHVtKTsKKwkJQW55QXJyYXlUeXBlSW5mbyAqbWV0YSA9IGFueWFycmF5X2dl
dF9tZXRhKGZjaW5mbywgZWxlbV90eXBlLCBmYWxzZSk7CisJCWJvb2wJICAgKm51bGxzOworCisJ
CUFOWUFSUkFZX0NIRUNLX0FSUkFZKGFycik7CisJCWtleXMgPSBleHRyYWN0X2FycmF5X2tleXMo
YXJyLCBtZXRhLCBuZW50cmllcywgJm51bGxzKTsKKworCQlzd2l0Y2ggKHN0cmF0KQorCQl7CisJ
CQljYXNlIEFOWUFSUkFZX0dJTl9PVkVSTEFQX1NUUkFURUdZOgorCQkJCSpzZWFyY2hNb2RlID0g
R0lOX1NFQVJDSF9NT0RFX0RFRkFVTFQ7CisJCQkJYnJlYWs7CisJCQljYXNlIEFOWUFSUkFZX0dJ
Tl9DT05UQUlORURfU1RSQVRFR1k6CisJCQkJKnNlYXJjaE1vZGUgPSBHSU5fU0VBUkNIX01PREVf
SU5DTFVERV9FTVBUWTsKKwkJCQlicmVhazsKKwkJCWNhc2UgQU5ZQVJSQVlfR0lOX0VRVUFMX1NU
UkFURUdZOgorCQkJCSpzZWFyY2hNb2RlID0gKCpuZW50cmllcyA+IDApCisJCQkJCT8gR0lOX1NF
QVJDSF9NT0RFX0RFRkFVTFQKKwkJCQkJOiBHSU5fU0VBUkNIX01PREVfSU5DTFVERV9FTVBUWTsK
KwkJCQlicmVhazsKKwkJCWNhc2UgQU5ZQVJSQVlfR0lOX0NPTlRBSU5TX1NUUkFURUdZOgorCQkJ
CSpzZWFyY2hNb2RlID0gKCpuZW50cmllcyA+IDApCisJCQkJCT8gR0lOX1NFQVJDSF9NT0RFX0RF
RkFVTFQKKwkJCQkJOiBHSU5fU0VBUkNIX01PREVfQUxMOworCQkJCWJyZWFrOworCQkJZGVmYXVs
dDoKKwkJCQllbG9nKEVSUk9SLCAiYW55YXJyYXlfZ2luOiB1bmtub3duIHN0cmF0ZWd5IG51bWJl
cjogJWQiLCBzdHJhdCk7CisJCX0KKworCQkodm9pZCkgbnVsbHM7CQkJLyogc3dhbGxvd2VkIGJ5
IGV4dHJhY3RfYXJyYXlfa2V5cyAqLworCQlQR19SRVRVUk5fUE9JTlRFUihrZXlzKTsKKwl9Cit9
CisKKworLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCisgKiAgQ29tbW9uOiBjb25zaXN0ZW50IGRpc3BhdGNo
ZXIKKyAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLQorICovCisKKy8qCisgKiBFdmFsdWF0ZSBhbiBhbnlxdWVy
eSBhZ2FpbnN0IGFuIGFycmF5IG9mICJrZXkgcHJlc2VudCIgZmxhZ3MuICBUaGUgaS10aAorICog
VkFMIGluIHBvc3RmaXggb3JkZXIgY29ycmVzcG9uZHMgdG8gY2hlY2tbaV0gKHdlIG1hcHBlZCB0
aGVtIGluCisgKiBleHRyYWN0UXVlcnksIHNvIHRoZSBqLXRoIFZBTCB3ZSBlbWl0dGVkIGlzIGNo
ZWNrW2pdKS4gIFdlIHJlYnVpbGQgdGhhdAorICogVkFMLW9ubHkgbWFwcGluZyBoZXJlIGFzIHdl
IHdhbGsgdGhlIHBvc3RmaXggdHJlZS4KKyAqLwordHlwZWRlZiBzdHJ1Y3QgQW55UXVlcnlDaGVj
aworeworCWNvbnN0IGJvb2wgKmNoZWNrOwkJCS8qIEdJTidzIHByZXNlbnQta2V5IGZsYWdzICov
CisJaW50CQkJbmV4dDsJCQkvKiBuZXh0IGluZGV4IGluIGNoZWNrW10gKi8KK30gQW55UXVlcnlD
aGVjazsKKworc3RhdGljIGJvb2wKK2V2YWxfd2l0aF9jaGVjayhBbnlRdWVyeSAqcSwgaW50IGlk
eCwgYm9vbCAqdmFscykKK3sKKwlBbnlRdWVyeUl0ZW0gKml0ID0gJnEtPml0ZW1zW2lkeF07CisK
KwlpZiAoaXQtPnR5cGUgPT0gQU5ZUV9WQUwpCisJCXJldHVybiB2YWxzW2lkeF07CisJaWYgKGl0
LT5wYXlsb2FkID09IEFOWVFfTk9UKQorCQlyZXR1cm4gIWV2YWxfd2l0aF9jaGVjayhxLCBpZHgg
LSAxLCB2YWxzKTsKKwlpZiAoaXQtPnBheWxvYWQgPT0gQU5ZUV9BTkQpCisJCXJldHVybiBldmFs
X3dpdGhfY2hlY2socSwgaWR4ICsgaXQtPmxlZnQsIHZhbHMpICYmCisJCQlldmFsX3dpdGhfY2hl
Y2socSwgaWR4IC0gMSwgdmFscyk7CisJLyogT1IgKi8KKwlyZXR1cm4gZXZhbF93aXRoX2NoZWNr
KHEsIGlkeCArIGl0LT5sZWZ0LCB2YWxzKSB8fAorCQlldmFsX3dpdGhfY2hlY2socSwgaWR4IC0g
MSwgdmFscyk7Cit9CisKK3N0YXRpYyBEYXR1bQorZG9fZ2luX2NvbnNpc3RlbnQoRnVuY3Rpb25D
YWxsSW5mbyBmY2luZm8sIE9pZCBlbGVtX3R5cGUpCit7CisJYm9vbAkgICAqY2hlY2sgPSAoYm9v
bCAqKSBQR19HRVRBUkdfUE9JTlRFUigwKTsKKwlTdHJhdGVneU51bWJlciBzdHJhdCA9IFBHX0dF
VEFSR19VSU5UMTYoMSk7CisJRGF0dW0JCXF1ZXJ5RGF0dW0gPSBQR19HRVRBUkdfREFUVU0oMik7
CisJaW50MzIJCW5rZXlzID0gUEdfR0VUQVJHX0lOVDMyKDMpOworCisJLyogUEdfR0VUQVJHX1BP
SU5URVIoNCk6IGV4dHJhX2RhdGEgLS0gbm90IHVzZWQgKi8KKwlib29sCSAgICpyZWNoZWNrID0g
KGJvb2wgKikgUEdfR0VUQVJHX1BPSU5URVIoNSk7CisJYm9vbAkJcmVzdWx0ID0gZmFsc2U7CisJ
aW50CQkJaTsKKworCSh2b2lkKSBlbGVtX3R5cGU7CisKKwlpZiAoc3RyYXQgPT0gQU5ZQVJSQVlf
R0lOX0JPT0xFQU5fU1RSQVRFR1kpCisJeworCQlBbnlRdWVyeSAgICpxID0gRGF0dW1HZXRBbnlR
dWVyeVAocXVlcnlEYXR1bSk7CisJCWJvb2wJICAgKnZhbHM7CisJCWludAkJCWsgPSAwOworCisJ
CSpyZWNoZWNrID0gZmFsc2U7CisKKwkJaWYgKHEtPnNpemUgPD0gMCkKKwkJCVBHX1JFVFVSTl9C
T09MKGZhbHNlKTsKKworCQkvKiBNYXAgZWFjaCBWQUwgcG9zdGZpeCBzbG90IHRvIGl0cyBwb3Np
dGlvbiBpbiBjaGVja1tdLiAqLworCQl2YWxzID0gKGJvb2wgKikgcGFsbG9jKHNpemVvZihib29s
KSAqIHEtPnNpemUpOworCQlmb3IgKGkgPSAwOyBpIDwgcS0+c2l6ZTsgaSsrKQorCQl7CisJCQlp
ZiAocS0+aXRlbXNbaV0udHlwZSA9PSBBTllRX1ZBTCkKKwkJCQl2YWxzW2ldID0gY2hlY2tbaysr
XTsKKwkJfQorCQlyZXN1bHQgPSBldmFsX3dpdGhfY2hlY2socSwgcS0+c2l6ZSAtIDEsIHZhbHMp
OworCQlwZnJlZSh2YWxzKTsKKwkJUEdfUkVUVVJOX0JPT0wocmVzdWx0KTsKKwl9CisKKwlzd2l0
Y2ggKHN0cmF0KQorCXsKKwkJY2FzZSBBTllBUlJBWV9HSU5fT1ZFUkxBUF9TVFJBVEVHWToKKwkJ
CSpyZWNoZWNrID0gZmFsc2U7CisKKwkJCS8qCisJCQkgKiBHSU4gZ3VhcmFudGVlcyBhdCBsZWFz
dCBvbmUgdHJ1ZSBlbnRyeSBvbiBlbnRyeTsgc2FmZSB0byBzYXkKKwkJCSAqIHllcworCQkJICov
CisJCQlmb3IgKGkgPSAwOyBpIDwgbmtleXM7IGkrKykKKwkJCXsKKwkJCQlpZiAoY2hlY2tbaV0p
CisJCQkJeworCQkJCQlyZXN1bHQgPSB0cnVlOworCQkJCQlicmVhazsKKwkJCQl9CisJCQl9CisJ
CQlicmVhazsKKwkJY2FzZSBBTllBUlJBWV9HSU5fQ09OVEFJTkVEX1NUUkFURUdZOgorCQkJKnJl
Y2hlY2sgPSB0cnVlOworCQkJcmVzdWx0ID0gdHJ1ZTsJCS8qIG11c3QgYWx3YXlzIHJlY2hlY2sg
Ki8KKwkJCWJyZWFrOworCQljYXNlIEFOWUFSUkFZX0dJTl9FUVVBTF9TVFJBVEVHWToKKwkJCSpy
ZWNoZWNrID0gdHJ1ZTsKKwkJCXJlc3VsdCA9IHRydWU7CisJCQlmb3IgKGkgPSAwOyBpIDwgbmtl
eXM7IGkrKykKKwkJCXsKKwkJCQlpZiAoIWNoZWNrW2ldKQorCQkJCXsKKwkJCQkJcmVzdWx0ID0g
ZmFsc2U7CisJCQkJCWJyZWFrOworCQkJCX0KKwkJCX0KKwkJCWJyZWFrOworCQljYXNlIEFOWUFS
UkFZX0dJTl9DT05UQUlOU19TVFJBVEVHWToKKwkJCSpyZWNoZWNrID0gZmFsc2U7CisJCQlyZXN1
bHQgPSB0cnVlOworCQkJZm9yIChpID0gMDsgaSA8IG5rZXlzOyBpKyspCisJCQl7CisJCQkJaWYg
KCFjaGVja1tpXSkKKwkJCQl7CisJCQkJCXJlc3VsdCA9IGZhbHNlOworCQkJCQlicmVhazsKKwkJ
CQl9CisJCQl9CisJCQlicmVhazsKKwkJZGVmYXVsdDoKKwkJCWVsb2coRVJST1IsICJhbnlhcnJh
eV9naW46IHVua25vd24gc3RyYXRlZ3kgbnVtYmVyOiAlZCIsIHN0cmF0KTsKKwl9CisKKwlQR19S
RVRVUk5fQk9PTChyZXN1bHQpOworfQorCisKKy8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQorICogIFBlci10
eXBlIHdyYXBwZXJzCisgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KKyAqLworCitEYXR1bQorYW55YXJyYXlf
Z2luX2V4dHJhY3RfcXVlcnlfaW50OChQR19GVU5DVElPTl9BUkdTKQoreworCXJldHVybiBkb19n
aW5fZXh0cmFjdF9xdWVyeShmY2luZm8sIElOVDhPSUQpOworfQorCitEYXR1bQorYW55YXJyYXlf
Z2luX2V4dHJhY3RfcXVlcnlfdXVpZChQR19GVU5DVElPTl9BUkdTKQoreworCXJldHVybiBkb19n
aW5fZXh0cmFjdF9xdWVyeShmY2luZm8sIFVVSURPSUQpOworfQorCitEYXR1bQorYW55YXJyYXlf
Z2luX2V4dHJhY3RfcXVlcnlfdGV4dChQR19GVU5DVElPTl9BUkdTKQoreworCXJldHVybiBkb19n
aW5fZXh0cmFjdF9xdWVyeShmY2luZm8sIFRFWFRPSUQpOworfQorCitEYXR1bQorYW55YXJyYXlf
Z2luX2NvbnNpc3RlbnRfaW50OChQR19GVU5DVElPTl9BUkdTKQoreworCXJldHVybiBkb19naW5f
Y29uc2lzdGVudChmY2luZm8sIElOVDhPSUQpOworfQorCitEYXR1bQorYW55YXJyYXlfZ2luX2Nv
bnNpc3RlbnRfdXVpZChQR19GVU5DVElPTl9BUkdTKQoreworCXJldHVybiBkb19naW5fY29uc2lz
dGVudChmY2luZm8sIFVVSURPSUQpOworfQorCitEYXR1bQorYW55YXJyYXlfZ2luX2NvbnNpc3Rl
bnRfdGV4dChQR19GVU5DVElPTl9BUkdTKQoreworCXJldHVybiBkb19naW5fY29uc2lzdGVudChm
Y2luZm8sIFRFWFRPSUQpOworfQpkaWZmIC0tZ2l0IGEvY29udHJpYi9hbnlhcnJheS9hbnlhcnJh
eV9naXN0LmMgYi9jb250cmliL2FueWFycmF5L2FueWFycmF5X2dpc3QuYwpuZXcgZmlsZSBtb2Rl
IDEwMDY0NAppbmRleCAwMDAwMDAwMDAwMC4uODk1NzBjNjNkZWQKLS0tIC9kZXYvbnVsbAorKysg
Yi9jb250cmliL2FueWFycmF5L2FueWFycmF5X2dpc3QuYwpAQCAtMCwwICsxLDc0MiBAQAorLyot
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tCisgKgorICogYW55YXJyYXlfZ2lzdC5jCisgKgkJU2lnbmF0dXJlLWJh
c2VkIEdpU1Qgb3BjbGFzcyBmb3IgYW55YXJyYXkuCisgKgorICogRWFjaCBpbmRleGVkIGFycmF5
IGlzIHN1bW1hcmlzZWQgYXMgYSBmaXhlZC1zaXplIGJpdCB2ZWN0b3I7IGVhY2ggZWxlbWVudAor
ICogY29udHJpYnV0ZXMgYSBzaW5nbGUgYml0IGNob3NlbiBieSBpdHMgaGFzaCBtb2R1bG8gdGhl
IHNpZ25hdHVyZSBsZW5ndGguCisgKiBJbnRlcm5hbCBub2RlIGtleXMgYXJlIGJpdHdpc2UgdW5p
b25zIG9mIHRoZWlyIGNoaWxkcmVuLCB3aXRoIGFuCisgKiBBTExJU1RSVUUgc2hvcnQtY2lyY3Vp
dCB3aGVuIGV2ZXJ5IGJpdCB3b3VsZCBiZSBzZXQuCisgKgorICogVGhlIG9wY2xhc3Mgc3VwcG9y
dHMgdGhlIGFycmF5IG9wZXJhdG9ycyAmJiwgQD4sIDxALCA9IGFuZCB0aGUgYW55YXJyYXkKKyAq
IGV4dGVuc2lvbidzIEBAIG9wZXJhdG9yLiAgQmVjYXVzZSBzaWduYXR1cmVzIGFyZSBsb3NzeSwg
YWxsIG1hdGNoZXMgYXJlCisgKiByZWNoZWNrZWQgYnkgR2lTVC4KKyAqCisgKiBDb3B5cmlnaHQg
KGMpIDIwMjYsIFBvc3RncmVTUUwgR2xvYmFsIERldmVsb3BtZW50IEdyb3VwCisgKgorICogSURF
TlRJRklDQVRJT04KKyAqCQljb250cmliL2FueWFycmF5L2FueWFycmF5X2dpc3QuYworICoKKyAq
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLQorICovCisKKyNpbmNsdWRlICJwb3N0Z3Jlcy5oIgorCisjaW5jbHVk
ZSAiYW55YXJyYXkuaCIKKworI2luY2x1ZGUgImFjY2Vzcy9naXN0LmgiCisjaW5jbHVkZSAiYWNj
ZXNzL3JlbG9wdGlvbnMuaCIKKyNpbmNsdWRlICJhY2Nlc3Mvc3RyYXRudW0uaCIKKyNpbmNsdWRl
ICJjYXRhbG9nL3BnX2luZGV4LmgiCisjaW5jbHVkZSAiY2F0YWxvZy9wZ190eXBlLmgiCisjaW5j
bHVkZSAibWlzY2FkbWluLmgiCisjaW5jbHVkZSAicG9ydC9wZ19iaXR1dGlscy5oIgorI2luY2x1
ZGUgInV0aWxzL2FycmF5LmgiCisjaW5jbHVkZSAidXRpbHMvYnVpbHRpbnMuaCIKKyNpbmNsdWRl
ICJ1dGlscy9sc3lzY2FjaGUuaCIKKyNpbmNsdWRlICJ1dGlscy9yZWwuaCIKKworLyogU3RyYXRl
Z3kgbnVtYmVyczsgc2hhcmUgUi10cmVlIGNvbnZlbnRpb25zIHdoZXJlIGFwcGxpY2FibGUuICov
CisjZGVmaW5lIEFOWUFSUkFZX09WRVJMQVBfU1RSQVRFR1kJCTMKKyNkZWZpbmUgQU5ZQVJSQVlf
Q09OVEFJTlNfU1RSQVRFR1kJCTcKKyNkZWZpbmUgQU5ZQVJSQVlfQ09OVEFJTkVEX1NUUkFURUdZ
CQk4CisjZGVmaW5lIEFOWUFSUkFZX0VRVUFMX1NUUkFURUdZCQkJMTgKKyNkZWZpbmUgQU5ZQVJS
QVlfQk9PTEVBTl9TVFJBVEVHWQkJMjAKKworUEdfRlVOQ1RJT05fSU5GT19WMShhbnlhcnJheV9n
aXN0X2tleV9pbik7CitQR19GVU5DVElPTl9JTkZPX1YxKGFueWFycmF5X2dpc3Rfa2V5X291dCk7
CitQR19GVU5DVElPTl9JTkZPX1YxKGFueWFycmF5X2dpc3RfY29uc2lzdGVudCk7CitQR19GVU5D
VElPTl9JTkZPX1YxKGFueWFycmF5X2dpc3RfY29tcHJlc3MpOworUEdfRlVOQ1RJT05fSU5GT19W
MShhbnlhcnJheV9naXN0X2RlY29tcHJlc3MpOworUEdfRlVOQ1RJT05fSU5GT19WMShhbnlhcnJh
eV9naXN0X3VuaW9uKTsKK1BHX0ZVTkNUSU9OX0lORk9fVjEoYW55YXJyYXlfZ2lzdF9zYW1lKTsK
K1BHX0ZVTkNUSU9OX0lORk9fVjEoYW55YXJyYXlfZ2lzdF9wZW5hbHR5KTsKK1BHX0ZVTkNUSU9O
X0lORk9fVjEoYW55YXJyYXlfZ2lzdF9waWNrc3BsaXQpOworUEdfRlVOQ1RJT05fSU5GT19WMShh
bnlhcnJheV9naXN0X29wdGlvbnMpOworCisKKy8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQorICogIFN0b3Jh
Z2UgdHlwZSBzdHVicworICoKKyAqICBUaGUgc2lnbmF0dXJlIGtleSBpcyBvbmx5IGV2ZXIgY29u
c3RydWN0ZWQgaW50ZXJuYWxseSBieSB0aGUgaW5kZXggQU0sCisgKiAgc28gaXRzIHRleHQgaW5w
dXQvb3V0cHV0IGZ1bmN0aW9ucyByZWplY3QgYWxsIGNhbGxzIChtaXJyb3JpbmcKKyAqICBpbnRi
aWdfZ2tleSBpbiBjb250cmliL2ludGFycmF5KS4KKyAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQorICovCisK
K0RhdHVtCithbnlhcnJheV9naXN0X2tleV9pbihQR19GVU5DVElPTl9BUkdTKQoreworCWVyZXBv
cnQoRVJST1IsCisJCQkoZXJyY29kZShFUlJDT0RFX0ZFQVRVUkVfTk9UX1NVUFBPUlRFRCksCisJ
CQkgZXJybXNnKCJjYW5ub3QgYWNjZXB0IGEgdmFsdWUgb2YgdHlwZSAlcyIsCisJCQkJCSJhbnlh
cnJheV9naXN0X2tleSIpKSk7CisJUEdfUkVUVVJOX1ZPSUQoKTsKK30KKworRGF0dW0KK2FueWFy
cmF5X2dpc3Rfa2V5X291dChQR19GVU5DVElPTl9BUkdTKQoreworCWVyZXBvcnQoRVJST1IsCisJ
CQkoZXJyY29kZShFUlJDT0RFX0ZFQVRVUkVfTk9UX1NVUFBPUlRFRCksCisJCQkgZXJybXNnKCJj
YW5ub3QgZGlzcGxheSBhIHZhbHVlIG9mIHR5cGUgJXMiLAorCQkJCQkiYW55YXJyYXlfZ2lzdF9r
ZXkiKSkpOworCVBHX1JFVFVSTl9WT0lEKCk7Cit9CisKKworLyogLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCisg
KiAgU2lnbmF0dXJlIGhlbHBlcnMKKyAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQorICovCisKK3N0YXRpYyBB
bnlBcnJheUdpc3RLZXkgKgorYWxsb2Nfa2V5KGJvb2wgYWxsaXN0cnVlLCBpbnQgc2lnbGVuLCBj
b25zdCB1bnNpZ25lZCBjaGFyICpzcmMpCit7CisJaW50MzIJCWZsYWcgPSBhbGxpc3RydWUgPyBB
TllBUlJBWV9BTExJU1RSVUUgOiAwOworCVNpemUJCXNpemUgPSBBTllBUlJBWV9HS0VZX1NJWkUo
ZmxhZywgc2lnbGVuKTsKKwlBbnlBcnJheUdpc3RLZXkgKmsgPSAoQW55QXJyYXlHaXN0S2V5ICop
IHBhbGxvYyhzaXplKTsKKworCVNFVF9WQVJTSVpFKGssIHNpemUpOworCWstPmZsYWcgPSBmbGFn
OworCWlmICghYWxsaXN0cnVlKQorCXsKKwkJaWYgKHNyYykKKwkJCW1lbWNweShrLT5kYXRhLCBz
cmMsIHNpZ2xlbik7CisJCWVsc2UKKwkJCW1lbXNldChrLT5kYXRhLCAwLCBzaWdsZW4pOworCX0K
KwlyZXR1cm4gazsKK30KKworLyoKKyAqIFNldCB0aGUgYml0IGNvcnJlc3BvbmRpbmcgdG8gInZh
bCIgKGEgYnRyZWUgaGFzaCB2YWx1ZSkgaW4gInNpZyIsIGEgYml0CisgKiB2ZWN0b3Igb2YgbGVu
Z3RoICJzaWdsZW4iIGJ5dGVzLgorICovCitzdGF0aWMgaW5saW5lIHZvaWQKK3NldF9iaXQodW5z
aWduZWQgY2hhciAqc2lnLCB1aW50MzIgaGFzaHZhbCwgaW50IHNpZ2xlbikKK3sKKwl1aW50MzIJ
CWJpdCA9IGhhc2h2YWwgJSAoKHVpbnQzMikgc2lnbGVuICogQklUU19QRVJfQllURSk7CisKKwlz
aWdbYml0IC8gQklUU19QRVJfQllURV0gfD0gKDFVIDw8IChiaXQgJSBCSVRTX1BFUl9CWVRFKSk7
Cit9CisKK3N0YXRpYyBpbmxpbmUgYm9vbAorZ2V0X2JpdChjb25zdCB1bnNpZ25lZCBjaGFyICpz
aWcsIHVpbnQzMiBoYXNodmFsLCBpbnQgc2lnbGVuKQoreworCXVpbnQzMgkJYml0ID0gaGFzaHZh
bCAlICgodWludDMyKSBzaWdsZW4gKiBCSVRTX1BFUl9CWVRFKTsKKworCXJldHVybiAoc2lnW2Jp
dCAvIEJJVFNfUEVSX0JZVEVdID4+IChiaXQgJSBCSVRTX1BFUl9CWVRFKSkgJiAxOworfQorCisv
KgorICogSGFzaCBhIHNpbmdsZSBEYXR1bSBvZiB0aGUgZ2l2ZW4gZWxlbWVudCB0eXBlLCByZXR1
cm5pbmcgYW4gdW5zaWduZWQgMzItYml0CisgKiB2YWx1ZSBzdWl0YWJsZSBmb3IgaW5kZXhpbmcg
dGhlIGJpdCB2ZWN0b3IuCisgKi8KK3N0YXRpYyB1aW50MzIKK2hhc2hfZWxlbShBbnlBcnJheVR5
cGVJbmZvICptZXRhLCBEYXR1bSB2YWx1ZSkKK3sKKwlEYXR1bQkJaCA9IEZ1bmN0aW9uQ2FsbDFD
b2xsKCZtZXRhLT5oYXNoX3Byb2MsIG1ldGEtPnR5cGNvbGxhdGlvbiwKKwkJCQkJCQkJCSAgdmFs
dWUpOworCisJcmV0dXJuICh1aW50MzIpIERhdHVtR2V0SW50MzIoaCk7Cit9CisKKy8qCisgKiBI
YXNoIGVhY2ggZWxlbWVudCBvZiAiYXJyIiBpbnRvICJzaWciLiAgVGhlIG1ldGFkYXRhIG11c3Qg
aGF2ZSBhIHZhbGlkCisgKiBoYXNoX3Byb2MgKHVzZSBhbnlhcnJheV9nZXRfbWV0YSguLi4sIHRy
dWUpKS4KKyAqLworc3RhdGljIHZvaWQKK2hhc2hfYXJyYXlfaW50byh1bnNpZ25lZCBjaGFyICpz
aWcsIGludCBzaWdsZW4sCisJCQkJQXJyYXlUeXBlICphcnIsIEFueUFycmF5VHlwZUluZm8gKm1l
dGEpCit7CisJRGF0dW0JICAgKnZhbHVlczsKKwlib29sCSAgICpudWxsczsKKwlpbnQJCQluZWxl
bXM7CisJaW50CQkJaTsKKworCWlmIChBUlJfTkRJTShhcnIpID09IDApCisJCXJldHVybjsKKwor
CWRlY29uc3RydWN0X2FycmF5KGFyciwgbWV0YS0+ZWxlbWVudF90eXBlLCBtZXRhLT50eXBsZW4s
CisJCQkJCSAgbWV0YS0+dHlwYnl2YWwsIG1ldGEtPnR5cGFsaWduLAorCQkJCQkgICZ2YWx1ZXMs
ICZudWxscywgJm5lbGVtcyk7CisKKwlmb3IgKGkgPSAwOyBpIDwgbmVsZW1zOyBpKyspCisJewor
CQlpZiAoIW51bGxzW2ldKQorCQkJc2V0X2JpdChzaWcsIGhhc2hfZWxlbShtZXRhLCB2YWx1ZXNb
aV0pLCBzaWdsZW4pOworCX0KKworCXBmcmVlKHZhbHVlcyk7CisJcGZyZWUobnVsbHMpOworfQor
CisvKiBDb3VudCAiMSIgYml0cyBpbiBhIGJ1ZmZlciBvZiAibiIgYnl0ZXMuICovCitzdGF0aWMg
aW50Citwb3Bjb3VudF9ieXRlcyhjb25zdCB1bnNpZ25lZCBjaGFyICpwLCBpbnQgbikKK3sKKwly
ZXR1cm4gcGdfcG9wY291bnQoKGNvbnN0IGNoYXIgKikgcCwgbik7Cit9CisKKworLyogLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tCisgKiAgY29tcHJlc3MgLyBkZWNvbXByZXNzCisgKiAtLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0K
KyAqLworCitEYXR1bQorYW55YXJyYXlfZ2lzdF9jb21wcmVzcyhQR19GVU5DVElPTl9BUkdTKQor
eworCUdJU1RFTlRSWSAgKmVudHJ5ID0gKEdJU1RFTlRSWSAqKSBQR19HRVRBUkdfUE9JTlRFUigw
KTsKKwlHSVNURU5UUlkgICpyZXR2YWwgPSBlbnRyeTsKKwlpbnQJCQlzaWdsZW4gPSBBTllBUlJB
WV9HRVRfU0lHTEVOKCk7CisKKwlpZiAoZW50cnktPmxlYWZrZXkpCisJeworCQlBcnJheVR5cGUg
ICphcnIgPSBEYXR1bUdldEFycmF5VHlwZVAoZW50cnktPmtleSk7CisJCUFueUFycmF5R2lzdEtl
eSAqa2V5OworCQlBbnlBcnJheVR5cGVJbmZvICptZXRhOworCisJCUFOWUFSUkFZX0NIRUNLX0FS
UkFZKGFycik7CisKKwkJbWV0YSA9IGFueWFycmF5X2dldF9tZXRhKGZjaW5mbywgQVJSX0VMRU1U
WVBFKGFyciksIHRydWUpOworCisJCWtleSA9IGFsbG9jX2tleShmYWxzZSwgc2lnbGVuLCBOVUxM
KTsKKwkJaGFzaF9hcnJheV9pbnRvKEFOWUFSUkFZX0dLRVlfU0lHTihrZXkpLCBzaWdsZW4sIGFy
ciwgbWV0YSk7CisKKwkJcmV0dmFsID0gKEdJU1RFTlRSWSAqKSBwYWxsb2Moc2l6ZW9mKEdJU1RF
TlRSWSkpOworCQlnaXN0ZW50cnlpbml0KCpyZXR2YWwsIFBvaW50ZXJHZXREYXR1bShrZXkpLCBl
bnRyeS0+cmVsLCBlbnRyeS0+cGFnZSwKKwkJCQkJICBlbnRyeS0+b2Zmc2V0LCBmYWxzZSk7CisJ
fQorCWVsc2UgaWYgKCFBTllBUlJBWV9HS0VZX0lTQUxMVFJVRShEYXR1bUdldFBvaW50ZXIoZW50
cnktPmtleSkpKQorCXsKKwkJQW55QXJyYXlHaXN0S2V5ICprID0gKEFueUFycmF5R2lzdEtleSAq
KSBEYXR1bUdldFBvaW50ZXIoZW50cnktPmtleSk7CisKKwkJLyoKKwkJICogSWYgZXZlcnkgYml0
IGhhcHBlbnMgdG8gYmUgc2V0LCBzd2l0Y2ggdG8gQUxMSVNUUlVFIHN0b3JhZ2Ugc28KKwkJICog
c3Vic2VxdWVudCBvcGVyYXRpb25zIGRvbid0IGhhdmUgdG8gY29tcGFyZSBhIGZ1bGwgYml0IHZl
Y3Rvci4KKwkJICovCisJCWlmIChwb3Bjb3VudF9ieXRlcyhBTllBUlJBWV9HS0VZX1NJR04oayks
IHNpZ2xlbikgPT0KKwkJCXNpZ2xlbiAqIEJJVFNfUEVSX0JZVEUpCisJCXsKKwkJCUFueUFycmF5
R2lzdEtleSAqciA9IGFsbG9jX2tleSh0cnVlLCBzaWdsZW4sIE5VTEwpOworCisJCQlyZXR2YWwg
PSAoR0lTVEVOVFJZICopIHBhbGxvYyhzaXplb2YoR0lTVEVOVFJZKSk7CisJCQlnaXN0ZW50cnlp
bml0KCpyZXR2YWwsIFBvaW50ZXJHZXREYXR1bShyKSwgZW50cnktPnJlbCwgZW50cnktPnBhZ2Us
CisJCQkJCQkgIGVudHJ5LT5vZmZzZXQsIGZhbHNlKTsKKwkJfQorCX0KKworCVBHX1JFVFVSTl9Q
T0lOVEVSKHJldHZhbCk7Cit9CisKK0RhdHVtCithbnlhcnJheV9naXN0X2RlY29tcHJlc3MoUEdf
RlVOQ1RJT05fQVJHUykKK3sKKwlQR19SRVRVUk5fUE9JTlRFUihQR19HRVRBUkdfUE9JTlRFUigw
KSk7Cit9CisKKworLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCisgKiAgdW5pb24gLyBzYW1lIC8gcGVuYWx0
eSAvIHBpY2tzcGxpdCAvIG9wdGlvbnMKKyAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQorICovCisKK0RhdHVt
CithbnlhcnJheV9naXN0X3VuaW9uKFBHX0ZVTkNUSU9OX0FSR1MpCit7CisJR2lzdEVudHJ5VmVj
dG9yICplbnRyeXZlYyA9IChHaXN0RW50cnlWZWN0b3IgKikgUEdfR0VUQVJHX1BPSU5URVIoMCk7
CisJaW50CQkgICAqc2l6ZXAgPSAoaW50ICopIFBHX0dFVEFSR19QT0lOVEVSKDEpOworCWludAkJ
CXNpZ2xlbiA9IEFOWUFSUkFZX0dFVF9TSUdMRU4oKTsKKwlBbnlBcnJheUdpc3RLZXkgKm91dDsK
Kwl1bnNpZ25lZCBjaGFyICpzaWc7CisJaW50CQkJbiA9IGVudHJ5dmVjLT5uOworCWludAkJCWk7
CisJYm9vbAkJYWxsID0gZmFsc2U7CisKKwlvdXQgPSBhbGxvY19rZXkoZmFsc2UsIHNpZ2xlbiwg
TlVMTCk7CisJc2lnID0gQU5ZQVJSQVlfR0tFWV9TSUdOKG91dCk7CisKKwlmb3IgKGkgPSAwOyBp
IDwgbjsgaSsrKQorCXsKKwkJQW55QXJyYXlHaXN0S2V5ICprID0gKEFueUFycmF5R2lzdEtleSAq
KQorCQkJRGF0dW1HZXRQb2ludGVyKGVudHJ5dmVjLT52ZWN0b3JbaV0ua2V5KTsKKworCQlpZiAo
QU5ZQVJSQVlfR0tFWV9JU0FMTFRSVUUoaykpCisJCXsKKwkJCWFsbCA9IHRydWU7CisJCQlicmVh
azsKKwkJfQorCQlmb3IgKGludCBqID0gMDsgaiA8IHNpZ2xlbjsgaisrKQorCQkJc2lnW2pdIHw9
IEFOWUFSUkFZX0dLRVlfU0lHTihrKVtqXTsKKwl9CisKKwlpZiAoYWxsIHx8IHBvcGNvdW50X2J5
dGVzKHNpZywgc2lnbGVuKSA9PSBzaWdsZW4gKiBCSVRTX1BFUl9CWVRFKQorCXsKKwkJcGZyZWUo
b3V0KTsKKwkJb3V0ID0gYWxsb2Nfa2V5KHRydWUsIHNpZ2xlbiwgTlVMTCk7CisJfQorCisJKnNp
emVwID0gVkFSU0laRShvdXQpOworCVBHX1JFVFVSTl9QT0lOVEVSKG91dCk7Cit9CisKK0RhdHVt
CithbnlhcnJheV9naXN0X3NhbWUoUEdfRlVOQ1RJT05fQVJHUykKK3sKKwlBbnlBcnJheUdpc3RL
ZXkgKmEgPSAoQW55QXJyYXlHaXN0S2V5ICopIFBHX0dFVEFSR19QT0lOVEVSKDApOworCUFueUFy
cmF5R2lzdEtleSAqYiA9IChBbnlBcnJheUdpc3RLZXkgKikgUEdfR0VUQVJHX1BPSU5URVIoMSk7
CisJYm9vbAkgICAqcmVzdWx0ID0gKGJvb2wgKikgUEdfR0VUQVJHX1BPSU5URVIoMik7CisJaW50
CQkJc2lnbGVuID0gQU5ZQVJSQVlfR0VUX1NJR0xFTigpOworCisJaWYgKEFOWUFSUkFZX0dLRVlf
SVNBTExUUlVFKGEpIHx8IEFOWUFSUkFZX0dLRVlfSVNBTExUUlVFKGIpKQorCQkqcmVzdWx0ID0g
QU5ZQVJSQVlfR0tFWV9JU0FMTFRSVUUoYSkgJiYgQU5ZQVJSQVlfR0tFWV9JU0FMTFRSVUUoYik7
CisJZWxzZQorCQkqcmVzdWx0ID0gKG1lbWNtcChBTllBUlJBWV9HS0VZX1NJR04oYSksIEFOWUFS
UkFZX0dLRVlfU0lHTihiKSwKKwkJCQkJCSAgc2lnbGVuKSA9PSAwKTsKKworCVBHX1JFVFVSTl9Q
T0lOVEVSKHJlc3VsdCk7Cit9CisKKy8qCisgKiBIYW1taW5nIHdlaWdodCBvZiAob3JpZyBPUiBu
ZXcpIC0gSGFtbWluZyB3ZWlnaHQgb2Ygb3JpZzogdGhlIG51bWJlciBvZgorICogbmV3IGJpdHMg
YSBjaGlsZCB3b3VsZCBpbnRyb2R1Y2UuICBBTExJU1RSVUUgZW50cmllcyBoYXZlIHRoZSBtYXhp
bXVtCisgKiBwb3NzaWJsZSB3ZWlnaHQgKHNpZ2xlbio4KSBzbyB0aGUgYW5zd2VyIGlzIDAuCisg
Ki8KK0RhdHVtCithbnlhcnJheV9naXN0X3BlbmFsdHkoUEdfRlVOQ1RJT05fQVJHUykKK3sKKwlH
SVNURU5UUlkgICpvcmlnZW50cnkgPSAoR0lTVEVOVFJZICopIFBHX0dFVEFSR19QT0lOVEVSKDAp
OworCUdJU1RFTlRSWSAgKm5ld2VudHJ5ID0gKEdJU1RFTlRSWSAqKSBQR19HRVRBUkdfUE9JTlRF
UigxKTsKKwlmbG9hdAkgICAqcGVuYWx0eSA9IChmbG9hdCAqKSBQR19HRVRBUkdfUE9JTlRFUigy
KTsKKwlpbnQJCQlzaWdsZW4gPSBBTllBUlJBWV9HRVRfU0lHTEVOKCk7CisJQW55QXJyYXlHaXN0
S2V5ICpvcmlnID0gKEFueUFycmF5R2lzdEtleSAqKSBEYXR1bUdldFBvaW50ZXIob3JpZ2VudHJ5
LT5rZXkpOworCUFueUFycmF5R2lzdEtleSAqbmV3XyA9IChBbnlBcnJheUdpc3RLZXkgKikgRGF0
dW1HZXRQb2ludGVyKG5ld2VudHJ5LT5rZXkpOworCisJaWYgKEFOWUFSUkFZX0dLRVlfSVNBTExU
UlVFKG9yaWcpKQorCXsKKwkJKnBlbmFsdHkgPSAwLjA7CisJfQorCWVsc2UgaWYgKEFOWUFSUkFZ
X0dLRVlfSVNBTExUUlVFKG5ld18pKQorCXsKKwkJaW50CQkJb3JpZ19iaXRzID0gcG9wY291bnRf
Ynl0ZXMoQU5ZQVJSQVlfR0tFWV9TSUdOKG9yaWcpLCBzaWdsZW4pOworCisJCSpwZW5hbHR5ID0g
KGZsb2F0KSAoc2lnbGVuICogQklUU19QRVJfQllURSAtIG9yaWdfYml0cyk7CisJfQorCWVsc2UK
Kwl7CisJCXVuc2lnbmVkIGNoYXIgKm8gPSBBTllBUlJBWV9HS0VZX1NJR04ob3JpZyk7CisJCXVu
c2lnbmVkIGNoYXIgKm4gPSBBTllBUlJBWV9HS0VZX1NJR04obmV3Xyk7CisJCWludAkJCWFkZGVk
ID0gMDsKKworCQlmb3IgKGludCBpID0gMDsgaSA8IHNpZ2xlbjsgaSsrKQorCQl7CisJCQl1bnNp
Z25lZCBjaGFyIGV4dHJhID0gbltpXSAmIH5vW2ldOworCisJCQlhZGRlZCArPSBwZ19udW1iZXJf
b2Zfb25lc1tleHRyYV07CisJCX0KKwkJKnBlbmFsdHkgPSAoZmxvYXQpIGFkZGVkOworCX0KKwor
CVBHX1JFVFVSTl9QT0lOVEVSKHBlbmFsdHkpOworfQorCisvKgorICogU3RhbmRhcmQgc2lnbmF0
dXJlIHBpY2tzcGxpdDogc29ydCBlbnRyaWVzIGJ5IEhhbW1pbmcgd2VpZ2h0IGFuZCBzcGxpdAor
ICogZG93biB0aGUgbWlkZGxlLiAgVGhpcyBpc24ndCBvcHRpbWFsIGJ1dCBpcyBjb3JyZWN0IGFu
ZCBiYWxhbmNlZDsgdGhlCisgKiBmYW5jaWVyIEd1dHRtYW4tc3R5bGUgc3BsaXRzIHVzZWQgYnkg
aW50YmlnIGNhbiBiZSBhZGRlZCBsYXRlci4KKyAqLwordHlwZWRlZiBzdHJ1Y3QgUGlja1NwbGl0
RW50cnkKK3sKKwlPZmZzZXROdW1iZXIgb2Zmc2V0OworCWludAkJCXdlaWdodDsKK30gUGlja1Nw
bGl0RW50cnk7CisKK3N0YXRpYyBpbnQKK3BzcGxpdF9jbXAoY29uc3Qgdm9pZCAqYSwgY29uc3Qg
dm9pZCAqYikKK3sKKwlpbnQJCQl3YSA9ICgoY29uc3QgUGlja1NwbGl0RW50cnkgKikgYSktPndl
aWdodDsKKwlpbnQJCQl3YiA9ICgoY29uc3QgUGlja1NwbGl0RW50cnkgKikgYiktPndlaWdodDsK
KworCXJldHVybiAod2EgPiB3YikgLSAod2EgPCB3Yik7Cit9CisKK3N0YXRpYyB2b2lkCitvcl9p
bnRvKHVuc2lnbmVkIGNoYXIgKmRzdCwgY29uc3QgdW5zaWduZWQgY2hhciAqc3JjLCBpbnQgc2ln
bGVuKQoreworCWZvciAoaW50IGkgPSAwOyBpIDwgc2lnbGVuOyBpKyspCisJCWRzdFtpXSB8PSBz
cmNbaV07Cit9CisKK0RhdHVtCithbnlhcnJheV9naXN0X3BpY2tzcGxpdChQR19GVU5DVElPTl9B
UkdTKQoreworCUdpc3RFbnRyeVZlY3RvciAqZW50cnl2ZWMgPSAoR2lzdEVudHJ5VmVjdG9yICop
IFBHX0dFVEFSR19QT0lOVEVSKDApOworCUdJU1RfU1BMSVRWRUMgKnYgPSAoR0lTVF9TUExJVFZF
QyAqKSBQR19HRVRBUkdfUE9JTlRFUigxKTsKKwlpbnQJCQlzaWdsZW4gPSBBTllBUlJBWV9HRVRf
U0lHTEVOKCk7CisJaW50CQkJbiA9IGVudHJ5dmVjLT5uIC0gMTsJLyogZW50cmllcyBzdGFydCBh
dCBpbmRleCAxICovCisJUGlja1NwbGl0RW50cnkgKml0ZW1zOworCUFueUFycmF5R2lzdEtleSAq
bGVmdCwKKwkJCSAgICpyaWdodDsKKwlpbnQJCQlpOworCWludAkJCXNwbGl0OworCisJaXRlbXMg
PSAoUGlja1NwbGl0RW50cnkgKikgcGFsbG9jKG4gKiBzaXplb2YoUGlja1NwbGl0RW50cnkpKTsK
Kwlmb3IgKGkgPSAwOyBpIDwgbjsgaSsrKQorCXsKKwkJQW55QXJyYXlHaXN0S2V5ICprID0gKEFu
eUFycmF5R2lzdEtleSAqKQorCQkJRGF0dW1HZXRQb2ludGVyKGVudHJ5dmVjLT52ZWN0b3JbaSAr
IDFdLmtleSk7CisKKwkJaXRlbXNbaV0ub2Zmc2V0ID0gKE9mZnNldE51bWJlcikgKGkgKyAxKTsK
KwkJaXRlbXNbaV0ud2VpZ2h0ID0gQU5ZQVJSQVlfR0tFWV9JU0FMTFRSVUUoaykKKwkJCT8gc2ln
bGVuICogQklUU19QRVJfQllURQorCQkJOiBwb3Bjb3VudF9ieXRlcyhBTllBUlJBWV9HS0VZX1NJ
R04oayksIHNpZ2xlbik7CisJfQorCXFzb3J0KGl0ZW1zLCBuLCBzaXplb2YoUGlja1NwbGl0RW50
cnkpLCBwc3BsaXRfY21wKTsKKworCXYtPnNwbF9sZWZ0ID0gKE9mZnNldE51bWJlciAqKSBwYWxs
b2MobiAqIHNpemVvZihPZmZzZXROdW1iZXIpKTsKKwl2LT5zcGxfcmlnaHQgPSAoT2Zmc2V0TnVt
YmVyICopIHBhbGxvYyhuICogc2l6ZW9mKE9mZnNldE51bWJlcikpOworCXYtPnNwbF9ubGVmdCA9
IDA7CisJdi0+c3BsX25yaWdodCA9IDA7CisJbGVmdCA9IGFsbG9jX2tleShmYWxzZSwgc2lnbGVu
LCBOVUxMKTsKKwlyaWdodCA9IGFsbG9jX2tleShmYWxzZSwgc2lnbGVuLCBOVUxMKTsKKworCXNw
bGl0ID0gbiAvIDI7CisJaWYgKHNwbGl0ID09IDApCisJCXNwbGl0ID0gMTsKKwlpZiAoc3BsaXQg
PT0gbikKKwkJc3BsaXQgPSBuIC0gMTsKKworCWZvciAoaSA9IDA7IGkgPCBzcGxpdDsgaSsrKQor
CXsKKwkJQW55QXJyYXlHaXN0S2V5ICprID0gKEFueUFycmF5R2lzdEtleSAqKQorCQkJRGF0dW1H
ZXRQb2ludGVyKGVudHJ5dmVjLT52ZWN0b3JbaXRlbXNbaV0ub2Zmc2V0XS5rZXkpOworCisJCXYt
PnNwbF9sZWZ0W3YtPnNwbF9ubGVmdCsrXSA9IGl0ZW1zW2ldLm9mZnNldDsKKwkJaWYgKEFOWUFS
UkFZX0dLRVlfSVNBTExUUlVFKGspKQorCQl7CisJCQlwZnJlZShsZWZ0KTsKKwkJCWxlZnQgPSBh
bGxvY19rZXkodHJ1ZSwgc2lnbGVuLCBOVUxMKTsKKwkJfQorCQllbHNlIGlmICghQU5ZQVJSQVlf
R0tFWV9JU0FMTFRSVUUobGVmdCkpCisJCQlvcl9pbnRvKEFOWUFSUkFZX0dLRVlfU0lHTihsZWZ0
KSwgQU5ZQVJSQVlfR0tFWV9TSUdOKGspLCBzaWdsZW4pOworCX0KKwlmb3IgKDsgaSA8IG47IGkr
KykKKwl7CisJCUFueUFycmF5R2lzdEtleSAqayA9IChBbnlBcnJheUdpc3RLZXkgKikKKwkJCURh
dHVtR2V0UG9pbnRlcihlbnRyeXZlYy0+dmVjdG9yW2l0ZW1zW2ldLm9mZnNldF0ua2V5KTsKKwor
CQl2LT5zcGxfcmlnaHRbdi0+c3BsX25yaWdodCsrXSA9IGl0ZW1zW2ldLm9mZnNldDsKKwkJaWYg
KEFOWUFSUkFZX0dLRVlfSVNBTExUUlVFKGspKQorCQl7CisJCQlwZnJlZShyaWdodCk7CisJCQly
aWdodCA9IGFsbG9jX2tleSh0cnVlLCBzaWdsZW4sIE5VTEwpOworCQl9CisJCWVsc2UgaWYgKCFB
TllBUlJBWV9HS0VZX0lTQUxMVFJVRShyaWdodCkpCisJCQlvcl9pbnRvKEFOWUFSUkFZX0dLRVlf
U0lHTihyaWdodCksIEFOWUFSUkFZX0dLRVlfU0lHTihrKSwgc2lnbGVuKTsKKwl9CisKKwl2LT5z
cGxfbGRhdHVtID0gUG9pbnRlckdldERhdHVtKGxlZnQpOworCXYtPnNwbF9yZGF0dW0gPSBQb2lu
dGVyR2V0RGF0dW0ocmlnaHQpOworCisJcGZyZWUoaXRlbXMpOworCVBHX1JFVFVSTl9QT0lOVEVS
KHYpOworfQorCisvKiBvcGNsYXNzIG9wdGlvbnM6IGp1c3QgdGhlIHNpZ25hdHVyZSBsZW5ndGgs
IGluIGJ5dGVzICovCitzdGF0aWMgdm9pZAorZmlsbF9zaWdsZW5fZGVmYXVsdChpbnQgKnNpZ2xl
bikKK3sKKwkqc2lnbGVuID0gQU5ZQVJSQVlfU0lHTEVOX0RFRkFVTFQ7Cit9CisKK0RhdHVtCith
bnlhcnJheV9naXN0X29wdGlvbnMoUEdfRlVOQ1RJT05fQVJHUykKK3sKKwlsb2NhbF9yZWxvcHRz
ICpyZWxvcHRzID0gKGxvY2FsX3JlbG9wdHMgKikgUEdfR0VUQVJHX1BPSU5URVIoMCk7CisKKwlp
bml0X2xvY2FsX3JlbG9wdGlvbnMocmVsb3B0cywgc2l6ZW9mKEFueUFycmF5R2lzdE9wdGlvbnMp
KTsKKwlhZGRfbG9jYWxfaW50X3JlbG9wdGlvbihyZWxvcHRzLCAic2lnbGVuIiwKKwkJCQkJCQki
c2lnbmF0dXJlIGxlbmd0aCBpbiBieXRlcyIsCisJCQkJCQkJQU5ZQVJSQVlfU0lHTEVOX0RFRkFV
TFQsIDEsIEFOWUFSUkFZX1NJR0xFTl9NQVgsCisJCQkJCQkJb2Zmc2V0b2YoQW55QXJyYXlHaXN0
T3B0aW9ucywgc2lnbGVuKSk7CisKKwkodm9pZCkgZmlsbF9zaWdsZW5fZGVmYXVsdDsKKwlQR19S
RVRVUk5fVk9JRCgpOworfQorCisKKy8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQorICogIGNvbnNpc3RlbnQK
KyAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLQorICovCisKKy8qCisgKiBGb3Igb3ZlcmxhcDogYW55IHNpbmds
ZSBtYXRjaGluZyBiaXQgbWVhbnMgdGhlIGtleSBNSUdIVCBjb250YWluIHNvbWV0aGluZworICog
dGhlIHF1ZXJ5IHJlZmVyZW5jZXMuICBSZXR1cm5zIHRydWUgaWYgYXQgbGVhc3Qgb25lIGVsZW1l
bnQgb2YgInF1ZXJ5IgorICogaGFzaGVzIHRvIGEgc2V0IGJpdCBpbiAic2lnIjsgQUxMSVNUUlVF
IGtleXMgdHJpdmlhbGx5IHBhc3MuCisgKi8KK3N0YXRpYyBib29sCitzaWdfb3ZlcmxhcF9hcnJh
eShjb25zdCB1bnNpZ25lZCBjaGFyICpzaWcsIGludCBzaWdsZW4sCisJCQkJICBBcnJheVR5cGUg
KnF1ZXJ5LCBBbnlBcnJheVR5cGVJbmZvICptZXRhKQoreworCURhdHVtCSAgICp2YWx1ZXM7CisJ
Ym9vbAkgICAqbnVsbHM7CisJaW50CQkJbmVsZW1zOworCWludAkJCWk7CisJYm9vbAkJZm91bmQg
PSBmYWxzZTsKKworCWlmIChBUlJfTkRJTShxdWVyeSkgPT0gMCkKKwkJcmV0dXJuIGZhbHNlOwor
CisJZGVjb25zdHJ1Y3RfYXJyYXkocXVlcnksIG1ldGEtPmVsZW1lbnRfdHlwZSwgbWV0YS0+dHlw
bGVuLAorCQkJCQkgIG1ldGEtPnR5cGJ5dmFsLCBtZXRhLT50eXBhbGlnbiwKKwkJCQkJICAmdmFs
dWVzLCAmbnVsbHMsICZuZWxlbXMpOworCisJZm9yIChpID0gMDsgaSA8IG5lbGVtczsgaSsrKQor
CXsKKwkJaWYgKG51bGxzW2ldKQorCQkJY29udGludWU7CisJCWlmIChnZXRfYml0KHNpZywgaGFz
aF9lbGVtKG1ldGEsIHZhbHVlc1tpXSksIHNpZ2xlbikpCisJCXsKKwkJCWZvdW5kID0gdHJ1ZTsK
KwkJCWJyZWFrOworCQl9CisJfQorCXBmcmVlKHZhbHVlcyk7CisJcGZyZWUobnVsbHMpOworCXJl
dHVybiBmb3VuZDsKK30KKworLyoKKyAqIEZvciBjb250YWluczogZXZlcnkgZWxlbWVudCBvZiB0
aGUgcXVlcnkgbXVzdCBoYXNoIHRvIGEgc2V0IGJpdC4KKyAqIElmIGFueSByZXF1aXJlZCBiaXQg
aXMgbWlzc2luZyB0aGUga2V5IGNhbm5vdCBjb250YWluIHRoZSBxdWVyeS4KKyAqLworc3RhdGlj
IGJvb2wKK3NpZ19jb250YWluc19hcnJheShjb25zdCB1bnNpZ25lZCBjaGFyICpzaWcsIGludCBz
aWdsZW4sCisJCQkJICAgQXJyYXlUeXBlICpxdWVyeSwgQW55QXJyYXlUeXBlSW5mbyAqbWV0YSkK
K3sKKwlEYXR1bQkgICAqdmFsdWVzOworCWJvb2wJICAgKm51bGxzOworCWludAkJCW5lbGVtczsK
KwlpbnQJCQlpOworCWJvb2wJCW9rID0gdHJ1ZTsKKworCWlmIChBUlJfTkRJTShxdWVyeSkgPT0g
MCkKKwkJcmV0dXJuIHRydWU7CisKKwlkZWNvbnN0cnVjdF9hcnJheShxdWVyeSwgbWV0YS0+ZWxl
bWVudF90eXBlLCBtZXRhLT50eXBsZW4sCisJCQkJCSAgbWV0YS0+dHlwYnl2YWwsIG1ldGEtPnR5
cGFsaWduLAorCQkJCQkgICZ2YWx1ZXMsICZudWxscywgJm5lbGVtcyk7CisKKwlmb3IgKGkgPSAw
OyBpIDwgbmVsZW1zOyBpKyspCisJeworCQlpZiAobnVsbHNbaV0pCisJCQljb250aW51ZTsKKwkJ
aWYgKCFnZXRfYml0KHNpZywgaGFzaF9lbGVtKG1ldGEsIHZhbHVlc1tpXSksIHNpZ2xlbikpCisJ
CXsKKwkJCW9rID0gZmFsc2U7CisJCQlicmVhazsKKwkJfQorCX0KKwlwZnJlZSh2YWx1ZXMpOwor
CXBmcmVlKG51bGxzKTsKKwlyZXR1cm4gb2s7Cit9CisKKy8qCisgKiBSZWN1cnNpdmUgcG9zdGZp
eCBldmFsdWF0b3IgZm9yIHNpZ19ldmFsX3F1ZXJ5KCkuCisgKgorICogInZhbHMiIGhvbGRzIHRo
ZSBwcmVjb21wdXRlZCBzaWduYXR1cmUgbG9va3VwIGZvciBldmVyeSBWQUwgc2xvdC4gIE5PVAor
ICogaXMgbm9uLXJlc3RyaWN0aXZlIHVuZGVyIGEgc2lnbmF0dXJlICh0aGUgYml0IGNvdWxkIHN0
aWxsIGJlIHNldCBieSBzb21lCisgKiBvdGhlciBpbnNlcnRlZCBhcnJheSksIHNvIHdlIGNvbnNl
cnZhdGl2ZWx5IHJlcG9ydCB0cnVlIG9uIG5lZ2F0aW9uOyB0aGUKKyAqIEdpU1QgcmVjaGVjayBz
dGVwIHdpbGwgdGhlbiBmaWx0ZXIgb24gdGhlIHJlYWwgdmFsdWVzLgorICovCitzdGF0aWMgYm9v
bAorc2lnX2V2YWxfd2FsayhBbnlRdWVyeSAqcSwgaW50IGlkeCwgY29uc3QgYm9vbCAqdmFscykK
K3sKKwlBbnlRdWVyeUl0ZW0gKml0OworCisJY2hlY2tfc3RhY2tfZGVwdGgoKTsKKwlBc3NlcnQo
aWR4ID49IDApOworCWl0ID0gJnEtPml0ZW1zW2lkeF07CisKKwlpZiAoaXQtPnR5cGUgPT0gQU5Z
UV9WQUwpCisJCXJldHVybiB2YWxzW2lkeF07CisJaWYgKGl0LT5wYXlsb2FkID09IEFOWVFfTk9U
KQorCQlyZXR1cm4gdHJ1ZTsKKwlpZiAoaXQtPnBheWxvYWQgPT0gQU5ZUV9BTkQpCisJCXJldHVy
biBzaWdfZXZhbF93YWxrKHEsIGlkeCArIGl0LT5sZWZ0LCB2YWxzKSAmJgorCQkJc2lnX2V2YWxf
d2FsayhxLCBpZHggLSAxLCB2YWxzKTsKKwkvKiBBTllRX09SICovCisJcmV0dXJuIHNpZ19ldmFs
X3dhbGsocSwgaWR4ICsgaXQtPmxlZnQsIHZhbHMpIHx8CisJCXNpZ19ldmFsX3dhbGsocSwgaWR4
IC0gMSwgdmFscyk7Cit9CisKKy8qCisgKiBFdmFsdWF0ZSBhbiBhbnlxdWVyeSBhZ2FpbnN0IGEg
c2lnbmF0dXJlLiAgRWFjaCBWQUwgaXMgcGFyc2VkIHVzaW5nIHRoZQorICogZWxlbWVudCB0eXBl
J3MgdGV4dCBpbnB1dCwgaGFzaGVkLCB0aGVuIGxvb2tlZCB1cCBpbiB0aGUgc2lnbmF0dXJlLgor
ICovCitzdGF0aWMgYm9vbAorc2lnX2V2YWxfcXVlcnkoY29uc3QgdW5zaWduZWQgY2hhciAqc2ln
LCBpbnQgc2lnbGVuLAorCQkJICAgQW55UXVlcnkgKnEsIEFueUFycmF5VHlwZUluZm8gKm1ldGEs
CisJCQkgICBPaWQgaW5wdXRfZnVuYywgT2lkIGlucHV0X3R5cGlvcGFyYW0pCit7CisJYm9vbAkg
ICAqdmFsczsKKwlib29sCQlyZXN1bHQ7CisJaW50CQkJaTsKKworCWlmIChxLT5zaXplIDw9IDAp
CisJCXJldHVybiBmYWxzZTsKKworCXZhbHMgPSAoYm9vbCAqKSBwYWxsb2MwKHNpemVvZihib29s
KSAqIHEtPnNpemUpOworCisJZm9yIChpID0gMDsgaSA8IHEtPnNpemU7IGkrKykKKwl7CisJCUFu
eVF1ZXJ5SXRlbSAqaXQgPSAmcS0+aXRlbXNbaV07CisJCURhdHVtCQl2OworCisJCWlmIChpdC0+
dHlwZSAhPSBBTllRX1ZBTCkKKwkJCWNvbnRpbnVlOworCQl2ID0gT2lkSW5wdXRGdW5jdGlvbkNh
bGwoaW5wdXRfZnVuYywKKwkJCQkJCQkJIChjaGFyICopIEFOWVFVRVJZX1NUUklORyhxLCBpdCks
CisJCQkJCQkJCSBpbnB1dF90eXBpb3BhcmFtLCAtMSk7CisJCXZhbHNbaV0gPSBnZXRfYml0KHNp
ZywgaGFzaF9lbGVtKG1ldGEsIHYpLCBzaWdsZW4pOworCX0KKworCXJlc3VsdCA9IHNpZ19ldmFs
X3dhbGsocSwgcS0+c2l6ZSAtIDEsIHZhbHMpOworCXBmcmVlKHZhbHMpOworCXJldHVybiByZXN1
bHQ7Cit9CisKK0RhdHVtCithbnlhcnJheV9naXN0X2NvbnNpc3RlbnQoUEdfRlVOQ1RJT05fQVJH
UykKK3sKKwlHSVNURU5UUlkgICplbnRyeSA9IChHSVNURU5UUlkgKikgUEdfR0VUQVJHX1BPSU5U
RVIoMCk7CisJU3RyYXRlZ3lOdW1iZXIgc3RyYXQgPSAoU3RyYXRlZ3lOdW1iZXIpIFBHX0dFVEFS
R19VSU5UMTYoMik7CisJT2lkCQkJc3VidHlwZSA9IFBHX0dFVEFSR19PSUQoMyk7CisJYm9vbAkg
ICAqcmVjaGVjayA9IChib29sICopIFBHX0dFVEFSR19QT0lOVEVSKDQpOworCUFueUFycmF5R2lz
dEtleSAqa2V5ID0gKEFueUFycmF5R2lzdEtleSAqKSBEYXR1bUdldFBvaW50ZXIoZW50cnktPmtl
eSk7CisJaW50CQkJc2lnbGVuID0gQU5ZQVJSQVlfR0VUX1NJR0xFTigpOworCWJvb2wJCXJlc3Vs
dDsKKworCS8qIEFsbCBzaWduYXR1cmUtYmFzZWQgYW5zd2VycyByZXF1aXJlIGEgcmVjaGVjay4g
Ki8KKwkqcmVjaGVjayA9IHRydWU7CisKKwlpZiAoQU5ZQVJSQVlfR0tFWV9JU0FMTFRSVUUoa2V5
KSkKKwl7CisJCS8qIENhbm5vdCBwcnVuZSBhbnl0aGluZyBmcm9tIGFuIGFsbC10cnVlIHNpZ25h
dHVyZS4gKi8KKwkJUEdfUkVUVVJOX0JPT0wodHJ1ZSk7CisJfQorCisJKHZvaWQpIHN1YnR5cGU7
CisKKwlpZiAoc3RyYXQgPT0gQU5ZQVJSQVlfQk9PTEVBTl9TVFJBVEVHWSkKKwl7CisJCUFueVF1
ZXJ5ICAgKnEgPSBQR19HRVRBUkdfQU5ZUVVFUllfUCgxKTsKKwkJQW55QXJyYXlUeXBlSW5mbyAq
bWV0YTsKKwkJRm9ybV9wZ19pbmRleCBpbmQ7CisJCU9pZAkJCWNvbHR5cGU7CisJCU9pZAkJCWVs
ZW10eXBlOworCQlPaWQJCQlpbnB1dF9mdW5jOworCQlPaWQJCQlpbnB1dF90eXBpb3BhcmFtOwor
CisJCS8qCisJCSAqIFRoZSBxdWVyeSBpcyBhbnlxdWVyeSwgc28gd2UgcmVjb3ZlciB0aGUgZWxl
bWVudCB0eXBlIGZyb20gdGhlCisJCSAqIGluZGV4ZWQgY29sdW1uJ3MgcGdfaW5kZXggZW50cnku
ICBUaGUgaW5kZXgncyBvd24gcmRfYXR0IGdpdmVzIHRoZQorCQkgKiBTVE9SQUdFIHR5cGUgKGFu
eWFycmF5X2dpc3Rfa2V5KSwgbm90IHRoZSBvcmlnaW5hbCBhcnJheSB0eXBlLCBzbworCQkgKiB3
ZSByZWFkIHRoZSBpbmRyZWxpZCArIGluZGtleSBpbnN0ZWFkLgorCQkgKi8KKwkJaW5kID0gZW50
cnktPnJlbC0+cmRfaW5kZXg7CisJCWlmIChpbmQgPT0gTlVMTCB8fCBpbmQtPmluZG5hdHRzIDwg
MSkKKwkJCWVyZXBvcnQoRVJST1IsCisJCQkJCShlcnJjb2RlKEVSUkNPREVfSU5URVJOQUxfRVJS
T1IpLAorCQkJCQkgZXJybXNnKCJhbnlhcnJheSBHaVNUIGluZGV4IGhhcyBubyBrZXkgY29sdW1u
IikpKTsKKwkJY29sdHlwZSA9IGdldF9hdHR0eXBlKGluZC0+aW5kcmVsaWQsIGluZC0+aW5ka2V5
LnZhbHVlc1swXSk7CisJCWVsZW10eXBlID0gZ2V0X2VsZW1lbnRfdHlwZShjb2x0eXBlKTsKKwkJ
aWYgKCFPaWRJc1ZhbGlkKGVsZW10eXBlKSkKKwkJCWVyZXBvcnQoRVJST1IsCisJCQkJCShlcnJj
b2RlKEVSUkNPREVfREFUQVRZUEVfTUlTTUFUQ0gpLAorCQkJCQkgZXJybXNnKCJjYW5ub3QgZGV0
ZXJtaW5lIGVsZW1lbnQgdHlwZSBmb3IgYW55cXVlcnkgbWF0Y2giKSkpOworCisJCW1ldGEgPSBh
bnlhcnJheV9nZXRfbWV0YShmY2luZm8sIGVsZW10eXBlLCB0cnVlKTsKKwkJZ2V0VHlwZUlucHV0
SW5mbyhlbGVtdHlwZSwgJmlucHV0X2Z1bmMsICZpbnB1dF90eXBpb3BhcmFtKTsKKworCQlyZXN1
bHQgPSBzaWdfZXZhbF9xdWVyeShBTllBUlJBWV9HS0VZX1NJR04oa2V5KSwgc2lnbGVuLCBxLCBt
ZXRhLAorCQkJCQkJCQlpbnB1dF9mdW5jLCBpbnB1dF90eXBpb3BhcmFtKTsKKwkJUEdfRlJFRV9J
Rl9DT1BZKHEsIDEpOworCQlQR19SRVRVUk5fQk9PTChyZXN1bHQpOworCX0KKwllbHNlCisJewor
CQlBcnJheVR5cGUgICpxdWVyeSA9IFBHX0dFVEFSR19BUlJBWVRZUEVfUCgxKTsKKwkJQW55QXJy
YXlUeXBlSW5mbyAqbWV0YTsKKworCQlBTllBUlJBWV9DSEVDS19BUlJBWShxdWVyeSk7CisJCW1l
dGEgPSBhbnlhcnJheV9nZXRfbWV0YShmY2luZm8sIEFSUl9FTEVNVFlQRShxdWVyeSksIHRydWUp
OworCisJCXN3aXRjaCAoc3RyYXQpCisJCXsKKwkJCWNhc2UgQU5ZQVJSQVlfT1ZFUkxBUF9TVFJB
VEVHWToKKwkJCQlyZXN1bHQgPSBzaWdfb3ZlcmxhcF9hcnJheShBTllBUlJBWV9HS0VZX1NJR04o
a2V5KSwgc2lnbGVuLAorCQkJCQkJCQkJCSAgIHF1ZXJ5LCBtZXRhKTsKKwkJCQlicmVhazsKKwkJ
CWNhc2UgQU5ZQVJSQVlfQ09OVEFJTlNfU1RSQVRFR1k6CisJCQkJcmVzdWx0ID0gc2lnX2NvbnRh
aW5zX2FycmF5KEFOWUFSUkFZX0dLRVlfU0lHTihrZXkpLCBzaWdsZW4sCisJCQkJCQkJCQkJCXF1
ZXJ5LCBtZXRhKTsKKwkJCQlicmVhazsKKwkJCWNhc2UgQU5ZQVJSQVlfQ09OVEFJTkVEX1NUUkFU
RUdZOgorCisJCQkJLyoKKwkJCQkgKiBGb3IgImtleSA8QCBxdWVyeSIsIHNpZ25hdHVyZXMgY2Fu
bm90IGV4Y2x1ZGUgYSBub24tbGVhZgorCQkJCSAqIGtleSBiZWNhdXNlIGl0cyBiaXRzIG1heSBj
b21lIGZyb20gbWFueSBkaXN0aW5jdCBjaGlsZHJlbgorCQkJCSAqIHdoaWNoIG5lZWQgbm90IGlu
ZGl2aWR1YWxseSBiZSBjb250YWluZWQgaW4gcXVlcnkuIEFsd2F5cworCQkJCSAqIHJlY2hlY2su
CisJCQkJICovCisJCQkJaWYgKEdJU1RfTEVBRihlbnRyeSkpCisJCQkJeworCQkJCQkvKgorCQkJ
CQkgKiBBdCB0aGUgbGVhZiwgZXZlcnkgc2V0IGJpdCBtdXN0IGFsc28gaGF2ZSBiZWVuIHNldCBi
eQorCQkJCQkgKiB0aGUgcXVlcnkgKGkuZS4sIGVsZW1lbnQgaGFzaGVzIHRvIHRoYXQgYml0KS4K
KwkJCQkJICovCisJCQkJCXVuc2lnbmVkIGNoYXIgKnFzaWc7CisJCQkJCWludAkJCWk7CisKKwkJ
CQkJcXNpZyA9ICh1bnNpZ25lZCBjaGFyICopIHBhbGxvYzAoc2lnbGVuKTsKKwkJCQkJaGFzaF9h
cnJheV9pbnRvKHFzaWcsIHNpZ2xlbiwgcXVlcnksIG1ldGEpOworCQkJCQlyZXN1bHQgPSB0cnVl
OworCQkJCQlmb3IgKGkgPSAwOyBpIDwgc2lnbGVuOyBpKyspCisJCQkJCXsKKwkJCQkJCWlmIChB
TllBUlJBWV9HS0VZX1NJR04oa2V5KVtpXSAmIH5xc2lnW2ldKQorCQkJCQkJeworCQkJCQkJCXJl
c3VsdCA9IGZhbHNlOworCQkJCQkJCWJyZWFrOworCQkJCQkJfQorCQkJCQl9CisJCQkJCXBmcmVl
KHFzaWcpOworCQkJCX0KKwkJCQllbHNlCisJCQkJCXJlc3VsdCA9IHRydWU7CisJCQkJYnJlYWs7
CisJCQljYXNlIEFOWUFSUkFZX0VRVUFMX1NUUkFURUdZOgorCisJCQkJLyoKKwkJCQkgKiBUaGUg
bGVhZiBzaWduYXR1cmUgZm9yIGFuIGVxdWFsIHJvdyBjb250YWlucyBldmVyeSBiaXQgb2YKKwkJ
CQkgKiB0aGUgcXVlcnkncyBoYXNoOyBpbnRlcm5hbCB1bmlvbnMgY29udGFpbiBhdCBsZWFzdCB0
aG9zZQorCQkJCSAqIGJpdHMuICBTbyAia2V5IGNvbnRhaW5zIHF1ZXJ5IGJpdHMiIGlzIGEgc291
bmQKKwkJCQkgKiBvdmVyLWFwcHJveGltYXRpb24gdGhhdCByZWNoZWNrIHdpbGwgdGlnaHRlbi4K
KwkJCQkgKi8KKwkJCQlyZXN1bHQgPSBzaWdfY29udGFpbnNfYXJyYXkoQU5ZQVJSQVlfR0tFWV9T
SUdOKGtleSksIHNpZ2xlbiwKKwkJCQkJCQkJCQkJcXVlcnksIG1ldGEpOworCQkJCWJyZWFrOwor
CQkJZGVmYXVsdDoKKwkJCQllbG9nKEVSUk9SLCAidW5yZWNvZ25pemVkIHN0cmF0ZWd5IG51bWJl
cjogJWQiLCBzdHJhdCk7CisJCQkJcmVzdWx0ID0gZmFsc2U7CisJCQkJYnJlYWs7CisJCX0KKwor
CQlQR19GUkVFX0lGX0NPUFkocXVlcnksIDEpOworCQlQR19SRVRVUk5fQk9PTChyZXN1bHQpOwor
CX0KK30KZGlmZiAtLWdpdCBhL2NvbnRyaWIvYW55YXJyYXkvYW55YXJyYXlfb3AuYyBiL2NvbnRy
aWIvYW55YXJyYXkvYW55YXJyYXlfb3AuYwpuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAw
MDAwMDAwMC4uNDdhMDUwYmIwZTMKLS0tIC9kZXYvbnVsbAorKysgYi9jb250cmliL2FueWFycmF5
L2FueWFycmF5X29wLmMKQEAgLTAsMCArMSw2MTMgQEAKKy8qLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQorICoK
KyAqIGFueWFycmF5X29wLmMKKyAqCQlTZXQtc3R5bGUgb3BlcmF0aW9ucyBvbiBhcnJheXMgb2Yg
YW55IHR5cGUuCisgKgorICogQWxsIGZ1bmN0aW9ucyBhY2NlcHQgYW55YXJyYXkgLyBhbnllbGVt
ZW50IGlucHV0cyBhbmQgZGlzcGF0Y2ggdG8gdGhlCisgKiBlbGVtZW50IHR5cGUncyBidHJlZSBj
b21wYXJpc29uIGZ1bmN0aW9uIHRocm91Z2ggYW55YXJyYXlfZ2V0X21ldGEoKS4KKyAqIFRoZSBv
cGVyYXRpb25zIG1pcnJvciB0aGUgY29ycmVzcG9uZGluZyBpbnRhcnJheSBvcGVyYXRpb25zIGJ1
dCBhcmUKKyAqIHR5cGUtcG9seW1vcnBoaWMuCisgKgorICogQ29weXJpZ2h0IChjKSAyMDI2LCBQ
b3N0Z3JlU1FMIEdsb2JhbCBEZXZlbG9wbWVudCBHcm91cAorICoKKyAqIElERU5USUZJQ0FUSU9O
CisgKgkJY29udHJpYi9hbnlhcnJheS9hbnlhcnJheV9vcC5jCisgKgorICotLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tCisgKi8KKworI2luY2x1ZGUgInBvc3RncmVzLmgiCisKKyNpbmNsdWRlICJhbnlhcnJheS5o
IgorCisjaW5jbHVkZSAiY2F0YWxvZy9wZ190eXBlLmgiCisjaW5jbHVkZSAibGliL3F1bmlxdWUu
aCIKKyNpbmNsdWRlICJ1dGlscy9hcnJheS5oIgorI2luY2x1ZGUgInV0aWxzL2J1aWx0aW5zLmgi
CisjaW5jbHVkZSAidXRpbHMvbHN5c2NhY2hlLmgiCisKKworLyoKKyAqIGRlY29uc3RydWN0X2Fy
cl9tZXRhCisgKgkJUHVsbCBlbGVtZW50IHZhbHVlcyBvdXQgb2YgImFyciIgYW5kIGZpbGwgaW4g
IiptZXRhIiBmb3IgaXRzIHR5cGUuCisgKgorICogUmV0dXJucyBEYXR1bSBhcnJheSBpbiAqb3V0
X3ZhbHVlcyAocGFsbG9jJ2QpLCBjb3VudCBpbiAqb3V0X25lbGVtcy4gIFRoZQorICogaW5wdXQg
YXJyYXkgbXVzdCBhbHJlYWR5IGhhdmUgcGFzc2VkIEFOWUFSUkFZX0NIRUNLX0FSUkFZOyB3ZSBz
dGlsbCBnYXRlCisgKiBvbiBpdCBkZWZlbnNpdmVseSBiZWNhdXNlIGFsbCBlbnRyeSBwb2ludHMg
ZmVlZCB0aHJvdWdoIHRoaXMgaGVscGVyLgorICovCitzdGF0aWMgdm9pZAorZGVjb25zdHJ1Y3Rf
YXJyX21ldGEoRnVuY3Rpb25DYWxsSW5mbyBmY2luZm8sIEFycmF5VHlwZSAqYXJyLAorCQkJCQkg
QW55QXJyYXlUeXBlSW5mbyAqKm91dF9tZXRhLAorCQkJCQkgRGF0dW0gKipvdXRfdmFsdWVzLCBp
bnQgKm91dF9uZWxlbXMpCit7CisJQW55QXJyYXlUeXBlSW5mbyAqbWV0YTsKKwlEYXR1bQkgICAq
dmFsdWVzOworCWJvb2wJICAgKm51bGxzOworCWludAkJCW5lbGVtczsKKworCUFOWUFSUkFZX0NI
RUNLX0FSUkFZKGFycik7CisKKwltZXRhID0gYW55YXJyYXlfZ2V0X21ldGEoZmNpbmZvLCBBUlJf
RUxFTVRZUEUoYXJyKSwgZmFsc2UpOworCisJaWYgKEFSUl9ORElNKGFycikgPT0gMCkKKwl7CisJ
CSpvdXRfbWV0YSA9IG1ldGE7CisJCSpvdXRfdmFsdWVzID0gTlVMTDsKKwkJKm91dF9uZWxlbXMg
PSAwOworCQlyZXR1cm47CisJfQorCisJZGVjb25zdHJ1Y3RfYXJyYXkoYXJyLCBtZXRhLT5lbGVt
ZW50X3R5cGUsCisJCQkJCSAgbWV0YS0+dHlwbGVuLCBtZXRhLT50eXBieXZhbCwgbWV0YS0+dHlw
YWxpZ24sCisJCQkJCSAgJnZhbHVlcywgJm51bGxzLCAmbmVsZW1zKTsKKwlwZnJlZShudWxscyk7
CQkJCS8qIHdlJ3ZlIGFscmVhZHkgcmVqZWN0ZWQgbnVsbHMgYWJvdmUgKi8KKworCSpvdXRfbWV0
YSA9IG1ldGE7CisJKm91dF92YWx1ZXMgPSB2YWx1ZXM7CisJKm91dF9uZWxlbXMgPSBuZWxlbXM7
Cit9CisKKy8qCisgKiBtYWtlX2FycmF5X2Zyb21fZGF0dW1zCisgKgkJQnVpbGQgYSAxLUQgYXJy
YXkgZnJvbSB0aGUgZ2l2ZW4gRGF0dW0gdmVjdG9yLiAgRW1wdHkgLT4gZW1wdHkgYXJyYXkuCisg
Ki8KK3N0YXRpYyBBcnJheVR5cGUgKgorbWFrZV9hcnJheV9mcm9tX2RhdHVtcyhEYXR1bSAqdmFs
dWVzLCBpbnQgbmVsZW1zLCBBbnlBcnJheVR5cGVJbmZvICptZXRhKQoreworCWlmIChuZWxlbXMg
PT0gMCkKKwkJcmV0dXJuIGNvbnN0cnVjdF9lbXB0eV9hcnJheShtZXRhLT5lbGVtZW50X3R5cGUp
OworCisJcmV0dXJuIGNvbnN0cnVjdF9hcnJheSh2YWx1ZXMsIG5lbGVtcywgbWV0YS0+ZWxlbWVu
dF90eXBlLAorCQkJCQkJICAgbWV0YS0+dHlwbGVuLCBtZXRhLT50eXBieXZhbCwgbWV0YS0+dHlw
YWxpZ24pOworfQorCisKKy8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQorICogIHNvcnQgLyB1bmlxCisgKiAt
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0KKyAqLworCitQR19GVU5DVElPTl9JTkZPX1YxKGFueWFycmF5X3NvcnQp
OworUEdfRlVOQ1RJT05fSU5GT19WMShhbnlhcnJheV9zb3J0X2Rpcik7CitQR19GVU5DVElPTl9J
TkZPX1YxKGFueWFycmF5X3VuaXEpOworCisvKgorICogU29ydCBhbiBhcnJheSBhc2NlbmRpbmcu
CisgKi8KK0RhdHVtCithbnlhcnJheV9zb3J0KFBHX0ZVTkNUSU9OX0FSR1MpCit7CisJQXJyYXlU
eXBlICAqYXJyID0gUEdfR0VUQVJHX0FSUkFZVFlQRV9QKDApOworCUFueUFycmF5VHlwZUluZm8g
Km1ldGE7CisJRGF0dW0JICAgKnZhbHVlczsKKwlpbnQJCQluZWxlbXM7CisKKwlkZWNvbnN0cnVj
dF9hcnJfbWV0YShmY2luZm8sIGFyciwgJm1ldGEsICZ2YWx1ZXMsICZuZWxlbXMpOworCisJaWYg
KG5lbGVtcyA+IDEpCisJCXFzb3J0X2FyZyh2YWx1ZXMsIG5lbGVtcywgc2l6ZW9mKERhdHVtKSwg
YW55YXJyYXlfY21wX2RhdHVtLCBtZXRhKTsKKworCVBHX1JFVFVSTl9BUlJBWVRZUEVfUChtYWtl
X2FycmF5X2Zyb21fZGF0dW1zKHZhbHVlcywgbmVsZW1zLCBtZXRhKSk7Cit9CisKKy8qCisgKiBT
b3J0IGFuIGFycmF5LiAgVGhlIGRpcmVjdGlvbiB0ZXh0IGlzIGNhc2UtaW5zZW5zaXRpdmUgYW5k
IG11c3QgYmUgb25lIG9mCisgKiAnYXNjJyAvICdhc2NlbmRpbmcnIG9yICdkZXNjJyAvICdkZXNj
ZW5kaW5nJy4KKyAqLworRGF0dW0KK2FueWFycmF5X3NvcnRfZGlyKFBHX0ZVTkNUSU9OX0FSR1Mp
Cit7CisJQXJyYXlUeXBlICAqYXJyID0gUEdfR0VUQVJHX0FSUkFZVFlQRV9QKDApOworCXRleHQJ
ICAgKmRpciA9IFBHX0dFVEFSR19URVhUX1BQKDEpOworCWNvbnN0IGNoYXIgKmRpcnN0ciA9IFZB
UkRBVEFfQU5ZKGRpcik7CisJaW50CQkJZGlybGVuID0gVkFSU0laRV9BTllfRVhIRFIoZGlyKTsK
Kwlib29sCQlhc2NlbmRpbmc7CisJQW55QXJyYXlUeXBlSW5mbyAqbWV0YTsKKwlEYXR1bQkgICAq
dmFsdWVzOworCWludAkJCW5lbGVtczsKKworCWlmICgoZGlybGVuID09IDMgJiYgcGdfc3RybmNh
c2VjbXAoZGlyc3RyLCAiYXNjIiwgMykgPT0gMCkgfHwKKwkJKGRpcmxlbiA9PSA5ICYmIHBnX3N0
cm5jYXNlY21wKGRpcnN0ciwgImFzY2VuZGluZyIsIDkpID09IDApKQorCQlhc2NlbmRpbmcgPSB0
cnVlOworCWVsc2UgaWYgKChkaXJsZW4gPT0gNCAmJiBwZ19zdHJuY2FzZWNtcChkaXJzdHIsICJk
ZXNjIiwgNCkgPT0gMCkgfHwKKwkJCSAoZGlybGVuID09IDEwICYmIHBnX3N0cm5jYXNlY21wKGRp
cnN0ciwgImRlc2NlbmRpbmciLCAxMCkgPT0gMCkpCisJCWFzY2VuZGluZyA9IGZhbHNlOworCWVs
c2UKKwkJZXJlcG9ydChFUlJPUiwKKwkJCQkoZXJyY29kZShFUlJDT0RFX0lOVkFMSURfUEFSQU1F
VEVSX1ZBTFVFKSwKKwkJCQkgZXJybXNnKCJzZWNvbmQgcGFyYW1ldGVyIG11c3QgYmUgXCJhc2Nc
IiBvciBcImRlc2NcIiIpKSk7CisKKwlkZWNvbnN0cnVjdF9hcnJfbWV0YShmY2luZm8sIGFyciwg
Jm1ldGEsICZ2YWx1ZXMsICZuZWxlbXMpOworCisJaWYgKG5lbGVtcyA+IDEpCisJeworCQlxc29y
dF9hcmcodmFsdWVzLCBuZWxlbXMsIHNpemVvZihEYXR1bSksIGFueWFycmF5X2NtcF9kYXR1bSwg
bWV0YSk7CisJCWlmICghYXNjZW5kaW5nKQorCQl7CisJCQlEYXR1bQkgICAqbCA9IHZhbHVlczsK
KwkJCURhdHVtCSAgICpyID0gdmFsdWVzICsgbmVsZW1zIC0gMTsKKworCQkJd2hpbGUgKGwgPCBy
KQorCQkJeworCQkJCURhdHVtCQl0bXAgPSAqbDsKKworCQkJCSpsKysgPSAqcjsKKwkJCQkqci0t
ID0gdG1wOworCQkJfQorCQl9CisJfQorCisJUEdfUkVUVVJOX0FSUkFZVFlQRV9QKG1ha2VfYXJy
YXlfZnJvbV9kYXR1bXModmFsdWVzLCBuZWxlbXMsIG1ldGEpKTsKK30KKworLyoKKyAqIFJlbW92
ZSBkdXBsaWNhdGUgZWxlbWVudHM7IGRvZXMgbm90IHJlcXVpcmUgcHJlLXNvcnRlZCBpbnB1dC4K
KyAqLworRGF0dW0KK2FueWFycmF5X3VuaXEoUEdfRlVOQ1RJT05fQVJHUykKK3sKKwlBcnJheVR5
cGUgICphcnIgPSBQR19HRVRBUkdfQVJSQVlUWVBFX1AoMCk7CisJQW55QXJyYXlUeXBlSW5mbyAq
bWV0YTsKKwlEYXR1bQkgICAqdmFsdWVzOworCWludAkJCW5lbGVtczsKKwlpbnQJCQludW5pcXVl
OworCisJZGVjb25zdHJ1Y3RfYXJyX21ldGEoZmNpbmZvLCBhcnIsICZtZXRhLCAmdmFsdWVzLCAm
bmVsZW1zKTsKKworCWlmIChuZWxlbXMgPiAxKQorCXsKKwkJcXNvcnRfYXJnKHZhbHVlcywgbmVs
ZW1zLCBzaXplb2YoRGF0dW0pLCBhbnlhcnJheV9jbXBfZGF0dW0sIG1ldGEpOworCQludW5pcXVl
ID0gcXVuaXF1ZV9hcmcodmFsdWVzLCBuZWxlbXMsIHNpemVvZihEYXR1bSksCisJCQkJCQkJICBh
bnlhcnJheV9jbXBfZGF0dW0sIG1ldGEpOworCX0KKwllbHNlCisJCW51bmlxdWUgPSBuZWxlbXM7
CisKKwlQR19SRVRVUk5fQVJSQVlUWVBFX1AobWFrZV9hcnJheV9mcm9tX2RhdHVtcyh2YWx1ZXMs
IG51bmlxdWUsIG1ldGEpKTsKK30KKworCisvKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KKyAqICBpZHggLyBz
dWJhcnJheSAvIGNhcmRpbmFsaXR5CisgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KKyAqLworCitQR19GVU5D
VElPTl9JTkZPX1YxKGFueWFycmF5X2lkeCk7CitQR19GVU5DVElPTl9JTkZPX1YxKGFueWFycmF5
X3N1YmFycmF5KTsKK1BHX0ZVTkNUSU9OX0lORk9fVjEoYW55YXJyYXlfc3ViYXJyYXlfdG9fZW5k
KTsKK1BHX0ZVTkNUSU9OX0lORk9fVjEoYW55YXJyYXlfaWNvdW50KTsKKworLyoKKyAqIFJldHVy
biB0aGUgMS1iYXNlZCBpbmRleCBvZiB0aGUgZmlyc3Qgb2NjdXJyZW5jZSBvZiAiZWxlbSIgaW4g
ImFyciIsCisgKiBvciAwIGlmIG5vdCBmb3VuZC4KKyAqLworRGF0dW0KK2FueWFycmF5X2lkeChQ
R19GVU5DVElPTl9BUkdTKQoreworCUFycmF5VHlwZSAgKmFyciA9IFBHX0dFVEFSR19BUlJBWVRZ
UEVfUCgwKTsKKwlEYXR1bQkJZWxlbSA9IFBHX0dFVEFSR19EQVRVTSgxKTsKKwlBbnlBcnJheVR5
cGVJbmZvICptZXRhOworCURhdHVtCSAgICp2YWx1ZXM7CisJaW50CQkJbmVsZW1zOworCWludAkJ
CWk7CisKKwlkZWNvbnN0cnVjdF9hcnJfbWV0YShmY2luZm8sIGFyciwgJm1ldGEsICZ2YWx1ZXMs
ICZuZWxlbXMpOworCisJZm9yIChpID0gMDsgaSA8IG5lbGVtczsgaSsrKQorCXsKKwkJRGF0dW0J
CWVxID0gRnVuY3Rpb25DYWxsMkNvbGwoJm1ldGEtPmVxX3Byb2MsIG1ldGEtPnR5cGNvbGxhdGlv
biwKKwkJCQkJCQkJCQkgICB2YWx1ZXNbaV0sIGVsZW0pOworCisJCWlmIChEYXR1bUdldEJvb2wo
ZXEpKQorCQkJUEdfUkVUVVJOX0lOVDMyKGkgKyAxKTsKKwl9CisKKwlQR19SRVRVUk5fSU5UMzIo
MCk7Cit9CisKKy8qCisgKiBDb21tb24gc3ViYXJyYXkgZXh0cmFjdGlvbi4gICJzdGFydCIgaXMg
MS1iYXNlZDsgaWYgaXQgaXMgbm9uLXBvc2l0aXZlCisgKiB0aGUgZnVuY3Rpb24gcmV0dXJucyBh
biBlbXB0eSBhcnJheS4gICJsZW4iIGdpdmVzIHRoZSBtYXhpbXVtIG51bWJlciBvZgorICogZWxl
bWVudHMgdG8gY29weTsgaWYgImhhdmVfbGVuIiBpcyBmYWxzZSB0aGUgd2hvbGUgdGFpbCBpcyBy
ZXR1cm5lZC4KKyAqLworc3RhdGljIEFycmF5VHlwZSAqCitkb19zdWJhcnJheShGdW5jdGlvbkNh
bGxJbmZvIGZjaW5mbywgQXJyYXlUeXBlICphcnIsCisJCQlpbnQzMiBzdGFydCwgaW50MzIgbGVu
LCBib29sIGhhdmVfbGVuKQoreworCUFueUFycmF5VHlwZUluZm8gKm1ldGE7CisJRGF0dW0JICAg
KnZhbHVlczsKKwlpbnQJCQluZWxlbXM7CisJaW50CQkJb2ZmOworCWludAkJCW47CisKKwlkZWNv
bnN0cnVjdF9hcnJfbWV0YShmY2luZm8sIGFyciwgJm1ldGEsICZ2YWx1ZXMsICZuZWxlbXMpOwor
CisJaWYgKHN0YXJ0IDwgMSB8fCBzdGFydCA+IG5lbGVtcykKKwkJcmV0dXJuIGNvbnN0cnVjdF9l
bXB0eV9hcnJheShtZXRhLT5lbGVtZW50X3R5cGUpOworCisJb2ZmID0gc3RhcnQgLSAxOworCWlm
IChoYXZlX2xlbikKKwl7CisJCWlmIChsZW4gPD0gMCkKKwkJCXJldHVybiBjb25zdHJ1Y3RfZW1w
dHlfYXJyYXkobWV0YS0+ZWxlbWVudF90eXBlKTsKKwkJbiA9IE1pbihsZW4sIG5lbGVtcyAtIG9m
Zik7CisJfQorCWVsc2UKKwkJbiA9IG5lbGVtcyAtIG9mZjsKKworCXJldHVybiBtYWtlX2FycmF5
X2Zyb21fZGF0dW1zKHZhbHVlcyArIG9mZiwgbiwgbWV0YSk7Cit9CisKKy8qCisgKiBzdWJhcnJh
eShhcnIsIHN0YXJ0LCBsZW4pCisgKi8KK0RhdHVtCithbnlhcnJheV9zdWJhcnJheShQR19GVU5D
VElPTl9BUkdTKQoreworCUFycmF5VHlwZSAgKmFyciA9IFBHX0dFVEFSR19BUlJBWVRZUEVfUCgw
KTsKKwlpbnQzMgkJc3RhcnQgPSBQR19HRVRBUkdfSU5UMzIoMSk7CisJaW50MzIJCWxlbiA9IFBH
X0dFVEFSR19JTlQzMigyKTsKKworCVBHX1JFVFVSTl9BUlJBWVRZUEVfUChkb19zdWJhcnJheShm
Y2luZm8sIGFyciwgc3RhcnQsIGxlbiwgdHJ1ZSkpOworfQorCisvKgorICogc3ViYXJyYXkoYXJy
LCBzdGFydCkgLS0gdG8gZW5kCisgKi8KK0RhdHVtCithbnlhcnJheV9zdWJhcnJheV90b19lbmQo
UEdfRlVOQ1RJT05fQVJHUykKK3sKKwlBcnJheVR5cGUgICphcnIgPSBQR19HRVRBUkdfQVJSQVlU
WVBFX1AoMCk7CisJaW50MzIJCXN0YXJ0ID0gUEdfR0VUQVJHX0lOVDMyKDEpOworCisJUEdfUkVU
VVJOX0FSUkFZVFlQRV9QKGRvX3N1YmFycmF5KGZjaW5mbywgYXJyLCBzdGFydCwgMCwgZmFsc2Up
KTsKK30KKworLyoKKyAqIGljb3VudDogdG90YWwgZWxlbWVudCBjb3VudCwgaW50YXJyYXktc3R5
bGUuICBUaGlzIGR1cGxpY2F0ZXMKKyAqIGJ1aWx0LWluIGNhcmRpbmFsaXR5KCkgYnV0IHdlIGV4
cG9zZSBpdCB1bmRlciB0aGUgIyBvcGVyYXRvciB0aGUgd2F5CisgKiBpbnRhcnJheSBkb2VzLgor
ICovCitEYXR1bQorYW55YXJyYXlfaWNvdW50KFBHX0ZVTkNUSU9OX0FSR1MpCit7CisJQXJyYXlU
eXBlICAqYXJyID0gUEdfR0VUQVJHX0FSUkFZVFlQRV9QKDApOworCisJQU5ZQVJSQVlfQ0hFQ0tf
QVJSQVkoYXJyKTsKKwlQR19SRVRVUk5fSU5UMzIoQU5ZQVJSQVlfTkVMRU1TKGFycikpOworfQor
CisKKy8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLQorICogIGludGVyc2VjdCAvIHVuaW9uIC8gZGlmZmVyZW5j
ZQorICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tCisgKi8KKworUEdfRlVOQ1RJT05fSU5GT19WMShhbnlhcnJh
eV9pbnRlcnNlY3QpOworUEdfRlVOQ1RJT05fSU5GT19WMShhbnlhcnJheV91bmlvbik7CitQR19G
VU5DVElPTl9JTkZPX1YxKGFueWFycmF5X3VuaW9uX2VsZW0pOworUEdfRlVOQ1RJT05fSU5GT19W
MShhbnlhcnJheV9kaWZmZXJlbmNlKTsKK1BHX0ZVTkNUSU9OX0lORk9fVjEoYW55YXJyYXlfZGlm
ZmVyZW5jZV9lbGVtKTsKKworLyoKKyAqIGRlY29uc3RydWN0X3R3bworICoJCUxpa2UgZGVjb25z
dHJ1Y3RfYXJyX21ldGEoKSBidXQgZm9yIHR3byBhcnJheSBpbnB1dHMgdGhhdCBtdXN0IHNoYXJl
CisgKgkJYW4gZWxlbWVudCB0eXBlLiAgVGhlIHNlY29uZCBhcnJheSBpcyBhbGxvd2VkIHRvIGJl
IGEgZGlmZmVyZW50CisgKgkJQVJSQVkgT0lEIChpdCBtaWdodCBjb21lIGZyb20gYW5vdGhlciBj
b2x1bW4pIGFzIGxvbmcgYXMgdGhlIGVsZW1lbnQKKyAqCQl0eXBlcyBtYXRjaC4KKyAqLworc3Rh
dGljIEFueUFycmF5VHlwZUluZm8gKgorZGVjb25zdHJ1Y3RfdHdvKEZ1bmN0aW9uQ2FsbEluZm8g
ZmNpbmZvLAorCQkJCUFycmF5VHlwZSAqYSwgQXJyYXlUeXBlICpiLAorCQkJCURhdHVtICoqYXZh
bHMsIGludCAqYW5lbGVtcywKKwkJCQlEYXR1bSAqKmJ2YWxzLCBpbnQgKmJuZWxlbXMpCit7CisJ
QW55QXJyYXlUeXBlSW5mbyAqbWV0YTsKKwlib29sCSAgICpudWxsczsKKworCUFOWUFSUkFZX0NI
RUNLX0FSUkFZKGEpOworCUFOWUFSUkFZX0NIRUNLX0FSUkFZKGIpOworCisJaWYgKEFSUl9FTEVN
VFlQRShhKSAhPSBBUlJfRUxFTVRZUEUoYikpCisJCWVyZXBvcnQoRVJST1IsCisJCQkJKGVycmNv
ZGUoRVJSQ09ERV9EQVRBVFlQRV9NSVNNQVRDSCksCisJCQkJIGVycm1zZygiY2Fubm90IG9wZXJh
dGUgb24gYXJyYXlzIG9mIGRpZmZlcmVudCBlbGVtZW50IHR5cGVzIiksCisJCQkJIGVycmRldGFp
bCgiTGVmdCBvcGVyYW5kIGhhcyBlbGVtZW50IHR5cGUgJXMsIHJpZ2h0IG9wZXJhbmQgaGFzICVz
LiIsCisJCQkJCQkgICBmb3JtYXRfdHlwZV9iZShBUlJfRUxFTVRZUEUoYSkpLAorCQkJCQkJICAg
Zm9ybWF0X3R5cGVfYmUoQVJSX0VMRU1UWVBFKGIpKSkpKTsKKworCW1ldGEgPSBhbnlhcnJheV9n
ZXRfbWV0YShmY2luZm8sIEFSUl9FTEVNVFlQRShhKSwgZmFsc2UpOworCisJaWYgKEFSUl9ORElN
KGEpID09IDApCisJeworCQkqYXZhbHMgPSBOVUxMOworCQkqYW5lbGVtcyA9IDA7CisJfQorCWVs
c2UKKwl7CisJCWRlY29uc3RydWN0X2FycmF5KGEsIG1ldGEtPmVsZW1lbnRfdHlwZSwgbWV0YS0+
dHlwbGVuLAorCQkJCQkJICBtZXRhLT50eXBieXZhbCwgbWV0YS0+dHlwYWxpZ24sCisJCQkJCQkg
IGF2YWxzLCAmbnVsbHMsIGFuZWxlbXMpOworCQlwZnJlZShudWxscyk7CisJfQorCisJaWYgKEFS
Ul9ORElNKGIpID09IDApCisJeworCQkqYnZhbHMgPSBOVUxMOworCQkqYm5lbGVtcyA9IDA7CisJ
fQorCWVsc2UKKwl7CisJCWRlY29uc3RydWN0X2FycmF5KGIsIG1ldGEtPmVsZW1lbnRfdHlwZSwg
bWV0YS0+dHlwbGVuLAorCQkJCQkJICBtZXRhLT50eXBieXZhbCwgbWV0YS0+dHlwYWxpZ24sCisJ
CQkJCQkgIGJ2YWxzLCAmbnVsbHMsIGJuZWxlbXMpOworCQlwZnJlZShudWxscyk7CisJfQorCisJ
cmV0dXJuIG1ldGE7Cit9CisKKy8qCisgKiBTb3J0ICsgZGUtZHVwIGluIHBsYWNlLiAgUmV0dXJu
cyB0aGUgbmV3IGxlbmd0aC4KKyAqLworc3RhdGljIGludAorc29ydF91bmlxKERhdHVtICp2YWx1
ZXMsIGludCBuZWxlbXMsIEFueUFycmF5VHlwZUluZm8gKm1ldGEpCit7CisJaWYgKG5lbGVtcyA8
PSAxKQorCQlyZXR1cm4gbmVsZW1zOworCisJcXNvcnRfYXJnKHZhbHVlcywgbmVsZW1zLCBzaXpl
b2YoRGF0dW0pLCBhbnlhcnJheV9jbXBfZGF0dW0sIG1ldGEpOworCXJldHVybiBxdW5pcXVlX2Fy
Zyh2YWx1ZXMsIG5lbGVtcywgc2l6ZW9mKERhdHVtKSwKKwkJCQkJICAgYW55YXJyYXlfY21wX2Rh
dHVtLCBtZXRhKTsKK30KKworLyoKKyAqIEludGVyc2VjdGlvbjogcmV0dXJucyB0aGUgc29ydGVk
LCBkZWR1cGxpY2F0ZWQgdmFsdWVzIHByZXNlbnQgaW4gYm90aAorICogaW5wdXRzLgorICovCitE
YXR1bQorYW55YXJyYXlfaW50ZXJzZWN0KFBHX0ZVTkNUSU9OX0FSR1MpCit7CisJQXJyYXlUeXBl
ICAqYSA9IFBHX0dFVEFSR19BUlJBWVRZUEVfUCgwKTsKKwlBcnJheVR5cGUgICpiID0gUEdfR0VU
QVJHX0FSUkFZVFlQRV9QKDEpOworCUFueUFycmF5VHlwZUluZm8gKm1ldGE7CisJRGF0dW0JICAg
KmF2LAorCQkJICAgKmJ2LAorCQkJICAgKm91dDsKKwlpbnQJCQlhbiwKKwkJCQlibiwKKwkJCQlp
ID0gMCwKKwkJCQlqID0gMCwKKwkJCQlrID0gMDsKKworCW1ldGEgPSBkZWNvbnN0cnVjdF90d28o
ZmNpbmZvLCBhLCBiLCAmYXYsICZhbiwgJmJ2LCAmYm4pOworCisJYW4gPSBzb3J0X3VuaXEoYXYs
IGFuLCBtZXRhKTsKKwlibiA9IHNvcnRfdW5pcShidiwgYm4sIG1ldGEpOworCisJb3V0ID0gKERh
dHVtICopIHBhbGxvYyhzaXplb2YoRGF0dW0pICogTWluKGFuLCBibikpOworCXdoaWxlIChpIDwg
YW4gJiYgaiA8IGJuKQorCXsKKwkJaW50CQkJY21wID0gYW55YXJyYXlfY21wX2RhdHVtKCZhdltp
XSwgJmJ2W2pdLCBtZXRhKTsKKworCQlpZiAoY21wID09IDApCisJCXsKKwkJCW91dFtrKytdID0g
YXZbaV07CisJCQlpKys7CisJCQlqKys7CisJCX0KKwkJZWxzZSBpZiAoY21wIDwgMCkKKwkJCWkr
KzsKKwkJZWxzZQorCQkJaisrOworCX0KKworCVBHX1JFVFVSTl9BUlJBWVRZUEVfUChtYWtlX2Fy
cmF5X2Zyb21fZGF0dW1zKG91dCwgaywgbWV0YSkpOworfQorCisvKgorICogVW5pb246IHJldHVy
bnMgdGhlIHNvcnRlZCwgZGVkdXBsaWNhdGVkIHZhbHVlcyBwcmVzZW50IGluIGVpdGhlciBpbnB1
dC4KKyAqLworRGF0dW0KK2FueWFycmF5X3VuaW9uKFBHX0ZVTkNUSU9OX0FSR1MpCit7CisJQXJy
YXlUeXBlICAqYSA9IFBHX0dFVEFSR19BUlJBWVRZUEVfUCgwKTsKKwlBcnJheVR5cGUgICpiID0g
UEdfR0VUQVJHX0FSUkFZVFlQRV9QKDEpOworCUFueUFycmF5VHlwZUluZm8gKm1ldGE7CisJRGF0
dW0JICAgKmF2LAorCQkJICAgKmJ2LAorCQkJICAgKm91dDsKKwlpbnQJCQlhbiwKKwkJCQlibiwK
KwkJCQlpID0gMCwKKwkJCQlqID0gMCwKKwkJCQlrID0gMDsKKworCW1ldGEgPSBkZWNvbnN0cnVj
dF90d28oZmNpbmZvLCBhLCBiLCAmYXYsICZhbiwgJmJ2LCAmYm4pOworCisJYW4gPSBzb3J0X3Vu
aXEoYXYsIGFuLCBtZXRhKTsKKwlibiA9IHNvcnRfdW5pcShidiwgYm4sIG1ldGEpOworCisJb3V0
ID0gKERhdHVtICopIHBhbGxvYyhzaXplb2YoRGF0dW0pICogKGFuICsgYm4pKTsKKwl3aGlsZSAo
aSA8IGFuICYmIGogPCBibikKKwl7CisJCWludAkJCWNtcCA9IGFueWFycmF5X2NtcF9kYXR1bSgm
YXZbaV0sICZidltqXSwgbWV0YSk7CisKKwkJaWYgKGNtcCA9PSAwKQorCQl7CisJCQlvdXRbaysr
XSA9IGF2W2ldOworCQkJaSsrOworCQkJaisrOworCQl9CisJCWVsc2UgaWYgKGNtcCA8IDApCisJ
CQlvdXRbaysrXSA9IGF2W2krK107CisJCWVsc2UKKwkJCW91dFtrKytdID0gYnZbaisrXTsKKwl9
CisJd2hpbGUgKGkgPCBhbikKKwkJb3V0W2srK10gPSBhdltpKytdOworCXdoaWxlIChqIDwgYm4p
CisJCW91dFtrKytdID0gYnZbaisrXTsKKworCVBHX1JFVFVSTl9BUlJBWVRZUEVfUChtYWtlX2Fy
cmF5X2Zyb21fZGF0dW1zKG91dCwgaywgbWV0YSkpOworfQorCisvKgorICogYXJyYXkgfCBlbGVt
ZW50IDogYWRkIGVsZW1lbnQgaWYgbm90IGFscmVhZHkgcHJlc2VudCwgcmV0dXJuaW5nIHRoZQor
ICogc29ydGVkLCBkZWR1cGxpY2F0ZWQgcmVzdWx0LgorICovCitEYXR1bQorYW55YXJyYXlfdW5p
b25fZWxlbShQR19GVU5DVElPTl9BUkdTKQoreworCUFycmF5VHlwZSAgKmEgPSBQR19HRVRBUkdf
QVJSQVlUWVBFX1AoMCk7CisJRGF0dW0JCWVsZW0gPSBQR19HRVRBUkdfREFUVU0oMSk7CisJT2lk
CQkJZWxlbV90eXBlID0gZ2V0X2ZuX2V4cHJfYXJndHlwZShmY2luZm8tPmZsaW5mbywgMSk7CisJ
QW55QXJyYXlUeXBlSW5mbyAqbWV0YTsKKwlEYXR1bQkgICAqdmFsdWVzOworCWludAkJCW5lbGVt
czsKKwlpbnQJCQlvdXRfbjsKKworCUFOWUFSUkFZX0NIRUNLX0FSUkFZKGEpOworCisJaWYgKEFS
Ul9FTEVNVFlQRShhKSAhPSBlbGVtX3R5cGUpCisJCWVyZXBvcnQoRVJST1IsCisJCQkJKGVycmNv
ZGUoRVJSQ09ERV9EQVRBVFlQRV9NSVNNQVRDSCksCisJCQkJIGVycm1zZygiZWxlbWVudCB0eXBl
IGRvZXMgbm90IG1hdGNoIGFycmF5IGVsZW1lbnQgdHlwZSIpKSk7CisKKwltZXRhID0gYW55YXJy
YXlfZ2V0X21ldGEoZmNpbmZvLCBBUlJfRUxFTVRZUEUoYSksIGZhbHNlKTsKKworCWlmIChBUlJf
TkRJTShhKSA9PSAwKQorCXsKKwkJbmVsZW1zID0gMDsKKwkJdmFsdWVzID0gKERhdHVtICopIHBh
bGxvYyhzaXplb2YoRGF0dW0pKTsKKwl9CisJZWxzZQorCXsKKwkJYm9vbAkgICAqbnVsbHM7CisK
KwkJZGVjb25zdHJ1Y3RfYXJyYXkoYSwgbWV0YS0+ZWxlbWVudF90eXBlLCBtZXRhLT50eXBsZW4s
CisJCQkJCQkgIG1ldGEtPnR5cGJ5dmFsLCBtZXRhLT50eXBhbGlnbiwKKwkJCQkJCSAgJnZhbHVl
cywgJm51bGxzLCAmbmVsZW1zKTsKKwkJcGZyZWUobnVsbHMpOworCQl2YWx1ZXMgPSByZXBhbGxv
Yyh2YWx1ZXMsIHNpemVvZihEYXR1bSkgKiAobmVsZW1zICsgMSkpOworCX0KKworCXZhbHVlc1tu
ZWxlbXMrK10gPSBlbGVtOworCisJb3V0X24gPSBzb3J0X3VuaXEodmFsdWVzLCBuZWxlbXMsIG1l
dGEpOworCVBHX1JFVFVSTl9BUlJBWVRZUEVfUChtYWtlX2FycmF5X2Zyb21fZGF0dW1zKHZhbHVl
cywgb3V0X24sIG1ldGEpKTsKK30KKworLyoKKyAqIERpZmZlcmVuY2U6IHJldHVybnMgc29ydGVk
LCBkZWR1cGxpY2F0ZWQgdmFsdWVzIGZyb20gImEiIHRoYXQgYXJlIG5vdCBpbgorICogImIiLgor
ICovCitEYXR1bQorYW55YXJyYXlfZGlmZmVyZW5jZShQR19GVU5DVElPTl9BUkdTKQoreworCUFy
cmF5VHlwZSAgKmEgPSBQR19HRVRBUkdfQVJSQVlUWVBFX1AoMCk7CisJQXJyYXlUeXBlICAqYiA9
IFBHX0dFVEFSR19BUlJBWVRZUEVfUCgxKTsKKwlBbnlBcnJheVR5cGVJbmZvICptZXRhOworCURh
dHVtCSAgICphdiwKKwkJCSAgICpidiwKKwkJCSAgICpvdXQ7CisJaW50CQkJYW4sCisJCQkJYm4s
CisJCQkJaSA9IDAsCisJCQkJaiA9IDAsCisJCQkJayA9IDA7CisKKwltZXRhID0gZGVjb25zdHJ1
Y3RfdHdvKGZjaW5mbywgYSwgYiwgJmF2LCAmYW4sICZidiwgJmJuKTsKKworCWFuID0gc29ydF91
bmlxKGF2LCBhbiwgbWV0YSk7CisJYm4gPSBzb3J0X3VuaXEoYnYsIGJuLCBtZXRhKTsKKworCW91
dCA9IChEYXR1bSAqKSBwYWxsb2Moc2l6ZW9mKERhdHVtKSAqIGFuKTsKKwl3aGlsZSAoaSA8IGFu
ICYmIGogPCBibikKKwl7CisJCWludAkJCWNtcCA9IGFueWFycmF5X2NtcF9kYXR1bSgmYXZbaV0s
ICZidltqXSwgbWV0YSk7CisKKwkJaWYgKGNtcCA9PSAwKQorCQl7CisJCQlpKys7CisJCQlqKys7
CisJCX0KKwkJZWxzZSBpZiAoY21wIDwgMCkKKwkJCW91dFtrKytdID0gYXZbaSsrXTsKKwkJZWxz
ZQorCQkJaisrOworCX0KKwl3aGlsZSAoaSA8IGFuKQorCQlvdXRbaysrXSA9IGF2W2krK107CisK
KwlQR19SRVRVUk5fQVJSQVlUWVBFX1AobWFrZV9hcnJheV9mcm9tX2RhdHVtcyhvdXQsIGssIG1l
dGEpKTsKK30KKworLyoKKyAqIGFycmF5IC0gZWxlbWVudCA6IHJlbW92ZSBhbGwgb2NjdXJyZW5j
ZXMgb2YgImVsZW0iLCBwcmVzZXJ2aW5nIG9yZGVyLgorICogKE5vdGU6IGludGFycmF5IHJldHVy
bnMgdGhlIGlucHV0IG9yZGVyLXByZXNlcnZlZDsgd2UgZG8gdGhlIHNhbWUuKQorICovCitEYXR1
bQorYW55YXJyYXlfZGlmZmVyZW5jZV9lbGVtKFBHX0ZVTkNUSU9OX0FSR1MpCit7CisJQXJyYXlU
eXBlICAqYSA9IFBHX0dFVEFSR19BUlJBWVRZUEVfUCgwKTsKKwlEYXR1bQkJZWxlbSA9IFBHX0dF
VEFSR19EQVRVTSgxKTsKKwlPaWQJCQllbGVtX3R5cGUgPSBnZXRfZm5fZXhwcl9hcmd0eXBlKGZj
aW5mby0+ZmxpbmZvLCAxKTsKKwlBbnlBcnJheVR5cGVJbmZvICptZXRhOworCURhdHVtCSAgICp2
YWx1ZXM7CisJaW50CQkJbmVsZW1zOworCWludAkJCWksCisJCQkJayA9IDA7CisKKwlBTllBUlJB
WV9DSEVDS19BUlJBWShhKTsKKworCWlmIChBUlJfRUxFTVRZUEUoYSkgIT0gZWxlbV90eXBlKQor
CQllcmVwb3J0KEVSUk9SLAorCQkJCShlcnJjb2RlKEVSUkNPREVfREFUQVRZUEVfTUlTTUFUQ0gp
LAorCQkJCSBlcnJtc2coImVsZW1lbnQgdHlwZSBkb2VzIG5vdCBtYXRjaCBhcnJheSBlbGVtZW50
IHR5cGUiKSkpOworCisJbWV0YSA9IGFueWFycmF5X2dldF9tZXRhKGZjaW5mbywgQVJSX0VMRU1U
WVBFKGEpLCBmYWxzZSk7CisKKwlpZiAoQVJSX05ESU0oYSkgPT0gMCkKKwkJUEdfUkVUVVJOX0FS
UkFZVFlQRV9QKGNvbnN0cnVjdF9lbXB0eV9hcnJheShtZXRhLT5lbGVtZW50X3R5cGUpKTsKKwor
CXsKKwkJYm9vbAkgICAqbnVsbHM7CisKKwkJZGVjb25zdHJ1Y3RfYXJyYXkoYSwgbWV0YS0+ZWxl
bWVudF90eXBlLCBtZXRhLT50eXBsZW4sCisJCQkJCQkgIG1ldGEtPnR5cGJ5dmFsLCBtZXRhLT50
eXBhbGlnbiwKKwkJCQkJCSAgJnZhbHVlcywgJm51bGxzLCAmbmVsZW1zKTsKKwkJcGZyZWUobnVs
bHMpOworCX0KKworCWZvciAoaSA9IDA7IGkgPCBuZWxlbXM7IGkrKykKKwl7CisJCURhdHVtCQll
cSA9IEZ1bmN0aW9uQ2FsbDJDb2xsKCZtZXRhLT5lcV9wcm9jLCBtZXRhLT50eXBjb2xsYXRpb24s
CisJCQkJCQkJCQkJICAgdmFsdWVzW2ldLCBlbGVtKTsKKworCQlpZiAoIURhdHVtR2V0Qm9vbChl
cSkpCisJCQl2YWx1ZXNbaysrXSA9IHZhbHVlc1tpXTsKKwl9CisKKwlQR19SRVRVUk5fQVJSQVlU
WVBFX1AobWFrZV9hcnJheV9mcm9tX2RhdHVtcyh2YWx1ZXMsIGssIG1ldGEpKTsKK30KZGlmZiAt
LWdpdCBhL2NvbnRyaWIvYW55YXJyYXkvZXhwZWN0ZWQvYW55YXJyYXkub3V0IGIvY29udHJpYi9h
bnlhcnJheS9leHBlY3RlZC9hbnlhcnJheS5vdXQKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXgg
MDAwMDAwMDAwMDAuLmIxN2M2ZWYwMzNlCi0tLSAvZGV2L251bGwKKysrIGIvY29udHJpYi9hbnlh
cnJheS9leHBlY3RlZC9hbnlhcnJheS5vdXQKQEAgLTAsMCArMSw3MjcgQEAKK0NSRUFURSBFWFRF
TlNJT04gYW55YXJyYXk7CistLQorLS0gUGhhc2UgMTogc2V0IG9wZXJhdGlvbnMsIGhlbHBlcnMg
YW5kIG9wZXJhdG9ycyBmb3IgaW50OCwgdXVpZCwgdGV4dAorLS0KKy0tID09PT09IGludDggPT09
PT0KK1NFTEVDVCBhbnlhcnJheV9zb3J0KEFSUkFZWzMsIDEsIDIsIDFdOjppbnQ4W10pOworIGFu
eWFycmF5X3NvcnQgCistLS0tLS0tLS0tLS0tLS0KKyB7MSwxLDIsM30KKygxIHJvdykKKworU0VM
RUNUIGFueWFycmF5X3NvcnQoQVJSQVlbMywgMSwgMiwgMV06OmludDhbXSwgJ2Rlc2MnKTsKKyBh
bnlhcnJheV9zb3J0IAorLS0tLS0tLS0tLS0tLS0tCisgezMsMiwxLDF9CisoMSByb3cpCisKK1NF
TEVDVCBhbnlhcnJheV9zb3J0KEFSUkFZW106OmludDhbXSk7CisgYW55YXJyYXlfc29ydCAKKy0t
LS0tLS0tLS0tLS0tLQorIHt9CisoMSByb3cpCisKK1NFTEVDVCBhbnlhcnJheV91bmlxKEFSUkFZ
WzEsIDEsIDIsIDMsIDMsIDJdOjppbnQ4W10pOworIGFueWFycmF5X3VuaXEgCistLS0tLS0tLS0t
LS0tLS0KKyB7MSwyLDN9CisoMSByb3cpCisKK1NFTEVDVCBhbnlhcnJheV9pZHgoQVJSQVlbMTAs
IDIwLCAzMF06OmludDhbXSwgMjA6OmludDgpOworIGFueWFycmF5X2lkeCAKKy0tLS0tLS0tLS0t
LS0tCisgICAgICAgICAgICAyCisoMSByb3cpCisKK1NFTEVDVCBhbnlhcnJheV9pZHgoQVJSQVlb
MTAsIDIwLCAzMF06OmludDhbXSwgOTk6OmludDgpOworIGFueWFycmF5X2lkeCAKKy0tLS0tLS0t
LS0tLS0tCisgICAgICAgICAgICAwCisoMSByb3cpCisKK1NFTEVDVCBhbnlhcnJheV9zdWJhcnJh
eShBUlJBWVsxLDIsMyw0LDVdOjppbnQ4W10sIDIsIDIpOworIGFueWFycmF5X3N1YmFycmF5IAor
LS0tLS0tLS0tLS0tLS0tLS0tLQorIHsyLDN9CisoMSByb3cpCisKK1NFTEVDVCBhbnlhcnJheV9z
dWJhcnJheShBUlJBWVsxLDIsMyw0LDVdOjppbnQ4W10sIDMpOworIGFueWFycmF5X3N1YmFycmF5
IAorLS0tLS0tLS0tLS0tLS0tLS0tLQorIHszLDQsNX0KKygxIHJvdykKKworU0VMRUNUIGFueWFy
cmF5X3N1YmFycmF5KEFSUkFZWzEsMiwzXTo6aW50OFtdLCA1LCAxKTsKKyBhbnlhcnJheV9zdWJh
cnJheSAKKy0tLS0tLS0tLS0tLS0tLS0tLS0KKyB7fQorKDEgcm93KQorCitTRUxFQ1QgQVJSQVlb
MSwyLDNdOjppbnQ4W10gJiBBUlJBWVsyLDMsNF06OmludDhbXTsKKyA/Y29sdW1uPyAKKy0tLS0t
LS0tLS0KKyB7MiwzfQorKDEgcm93KQorCitTRUxFQ1QgQVJSQVlbMSwyLDNdOjppbnQ4W10gfCBB
UlJBWVszLDQsNV06OmludDhbXTsKKyAgP2NvbHVtbj8gICAKKy0tLS0tLS0tLS0tLS0KKyB7MSwy
LDMsNCw1fQorKDEgcm93KQorCitTRUxFQ1QgQVJSQVlbMSwyLDNdOjppbnQ4W10gfCA0OjppbnQ4
OworID9jb2x1bW4/ICAKKy0tLS0tLS0tLS0tCisgezEsMiwzLDR9CisoMSByb3cpCisKK1NFTEVD
VCBBUlJBWVsxLDIsMyw0XTo6aW50OFtdIC0gQVJSQVlbMiw0XTo6aW50OFtdOworID9jb2x1bW4/
IAorLS0tLS0tLS0tLQorIHsxLDN9CisoMSByb3cpCisKK1NFTEVDVCBBUlJBWVsxLDIsMiwzLDJd
OjppbnQ4W10gLSAyOjppbnQ4OworID9jb2x1bW4/IAorLS0tLS0tLS0tLQorIHsxLDN9CisoMSBy
b3cpCisKK1NFTEVDVCAjIEFSUkFZWzEwLDIwLDMwXTo6aW50OFtdOworID9jb2x1bW4/IAorLS0t
LS0tLS0tLQorICAgICAgICAzCisoMSByb3cpCisKK1NFTEVDVCBBUlJBWVsxMCwyMCwzMF06Omlu
dDhbXSAjIDIwOjppbnQ4OworID9jb2x1bW4/IAorLS0tLS0tLS0tLQorICAgICAgICAyCisoMSBy
b3cpCisKKy0tID09PT09IHV1aWQgPT09PT0KK1NFTEVDVCBhbnlhcnJheV9zb3J0KEFSUkFZWwor
ICAnMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAzJzo6dXVpZCwKKyAgJzAwMDAw
MDAwLTAwMDAtMDAwMC0wMDAwLTAwMDAwMDAwMDAwMScsCisgICcwMDAwMDAwMC0wMDAwLTAwMDAt
MDAwMC0wMDAwMDAwMDAwMDInXSk7CisgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgIGFueWFycmF5X3NvcnQgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAKKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQorIHswMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAw
MDAwMDAwMDEsMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAyLDAwMDAwMDAwLTAw
MDAtMDAwMC0wMDAwLTAwMDAwMDAwMDAwM30KKygxIHJvdykKKworU0VMRUNUIGFueWFycmF5X3Vu
aXEoQVJSQVlbCisgICcwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDEnOjp1dWlk
LAorICAnMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAxJywKKyAgJzAwMDAwMDAw
LTAwMDAtMDAwMC0wMDAwLTAwMDAwMDAwMDAwMiddKTsKKyAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgYW55YXJyYXlfdW5pcSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCist
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLQorIHswMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAw
MDEsMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAyfQorKDEgcm93KQorCitTRUxF
Q1QgYW55YXJyYXlfaWR4KEFSUkFZWworICAnMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAw
MDAwMDAxJzo6dXVpZCwKKyAgJzAwMDAwMDAwLTAwMDAtMDAwMC0wMDAwLTAwMDAwMDAwMDAwMidd
LAorICAnMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAyJzo6dXVpZCk7CisgYW55
YXJyYXlfaWR4IAorLS0tLS0tLS0tLS0tLS0KKyAgICAgICAgICAgIDIKKygxIHJvdykKKworU0VM
RUNUIEFSUkFZWycwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDEnOjp1dWlkLAor
ICAgICAgICAgICAgICcwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDInXQorICAg
ICAmIEFSUkFZWycwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDInOjp1dWlkLAor
ICAgICAgICAgICAgICcwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDMnXTsKKyAg
ICAgICAgICAgICAgICA/Y29sdW1uPyAgICAgICAgICAgICAgICAKKy0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KKyB7MDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAw
MDAwMDAyfQorKDEgcm93KQorCitTRUxFQ1QgQVJSQVlbJzAwMDAwMDAwLTAwMDAtMDAwMC0wMDAw
LTAwMDAwMDAwMDAwMSc6OnV1aWRdCisgICAgIHwgJzAwMDAwMDAwLTAwMDAtMDAwMC0wMDAwLTAw
MDAwMDAwMDAwMic6OnV1aWQ7CisgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgP2Nv
bHVtbj8gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAorLS0tLS0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
LS0tLS0KKyB7MDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAxLDAwMDAwMDAwLTAw
MDAtMDAwMC0wMDAwLTAwMDAwMDAwMDAwMn0KKygxIHJvdykKKworLS0gPT09PT0gdGV4dCA9PT09
PQorU0VMRUNUIGFueWFycmF5X3NvcnQoQVJSQVlbJ2JhbmFuYScsJ2FwcGxlJywnY2hlcnJ5J10p
OworICAgICBhbnlhcnJheV9zb3J0ICAgICAKKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCisge2Fw
cGxlLGJhbmFuYSxjaGVycnl9CisoMSByb3cpCisKK1NFTEVDVCBhbnlhcnJheV9zb3J0KEFSUkFZ
WydiYW5hbmEnLCdhcHBsZScsJ2NoZXJyeSddLCAnZGVzYycpOworICAgICBhbnlhcnJheV9zb3J0
ICAgICAKKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCisge2NoZXJyeSxiYW5hbmEsYXBwbGV9Ciso
MSByb3cpCisKK1NFTEVDVCBhbnlhcnJheV91bmlxKEFSUkFZWydhJywnYicsJ2EnLCdjJywnYidd
KTsKKyBhbnlhcnJheV91bmlxIAorLS0tLS0tLS0tLS0tLS0tCisge2EsYixjfQorKDEgcm93KQor
CitTRUxFQ1QgYW55YXJyYXlfaWR4KEFSUkFZWydhJywnYicsJ2MnXSwgJ2InOjp0ZXh0KTsKKyBh
bnlhcnJheV9pZHggCistLS0tLS0tLS0tLS0tLQorICAgICAgICAgICAgMgorKDEgcm93KQorCitT
RUxFQ1QgQVJSQVlbJ2EnLCdiJywnYyddOjp0ZXh0W10gJiBBUlJBWVsnYicsJ2MnLCdkJ106OnRl
eHRbXTsKKyA/Y29sdW1uPyAKKy0tLS0tLS0tLS0KKyB7YixjfQorKDEgcm93KQorCitTRUxFQ1Qg
QVJSQVlbJ2EnLCdiJywnYyddOjp0ZXh0W10gfCAnZCc6OnRleHQ7CisgP2NvbHVtbj8gIAorLS0t
LS0tLS0tLS0KKyB7YSxiLGMsZH0KKygxIHJvdykKKworU0VMRUNUIEFSUkFZWydhJywnYicsJ2Mn
LCdiJ106OnRleHRbXSAtICdiJzo6dGV4dDsKKyA/Y29sdW1uPyAKKy0tLS0tLS0tLS0KKyB7YSxj
fQorKDEgcm93KQorCistLSA9PT09PSBlcnJvciBjYXNlcyA9PT09PQorLS0gbXVsdGktZGltCitT
RUxFQ1QgYW55YXJyYXlfc29ydChBUlJBWVtbMSwyXSxbMyw0XV06OmludDhbXSk7CitFUlJPUjog
IG11bHRpZGltZW5zaW9uYWwgYXJyYXlzIGFyZSBub3Qgc3VwcG9ydGVkCistLSBudWxscworU0VM
RUNUIGFueWFycmF5X3NvcnQoQVJSQVlbMSwgTlVMTCwgMl06OmludDhbXSk7CitFUlJPUjogIGFy
cmF5IG11c3Qgbm90IGNvbnRhaW4gbnVsbHMKKy0tIGJhZCBkaXJlY3Rpb24KK1NFTEVDVCBhbnlh
cnJheV9zb3J0KEFSUkFZWzEsMiwzXTo6aW50OFtdLCAnYm9ndXMnKTsKK0VSUk9SOiAgc2Vjb25k
IHBhcmFtZXRlciBtdXN0IGJlICJhc2MiIG9yICJkZXNjIgorLS0KKy0tIFBoYXNlIDI6IGFueXF1
ZXJ5IGFuZCBAQCBvcGVyYXRvcgorLS0KKy0tIHBhcnNpbmcgKyBvdXRwdXQgcm91bmQtdHJpcAor
U0VMRUNUICcxICYgMic6OmFueXF1ZXJ5Ojp0ZXh0OworIHRleHQgIAorLS0tLS0tLQorIDEgJiAy
CisoMSByb3cpCisKK1NFTEVDVCAnMSAmIDIgfCAzJzo6YW55cXVlcnk6OnRleHQ7CisgICB0ZXh0
ICAgIAorLS0tLS0tLS0tLS0KKyAxICYgMiB8IDMKKygxIHJvdykKKworU0VMRUNUICcoMSB8IDIp
ICYgMyc6OmFueXF1ZXJ5Ojp0ZXh0OworICAgICB0ZXh0ICAgICAgCistLS0tLS0tLS0tLS0tLS0K
KyAoIDEgfCAyICkgJiAzCisoMSByb3cpCisKK1NFTEVDVCAnITEgJiAyJzo6YW55cXVlcnk6OnRl
eHQ7CisgIHRleHQgIAorLS0tLS0tLS0KKyAhMSAmIDIKKygxIHJvdykKKworU0VMRUNUICchKDEg
fCAyKSAmIDMnOjphbnlxdWVyeTo6dGV4dDsKKyAgICAgICAgdGV4dCAgICAgICAgCistLS0tLS0t
LS0tLS0tLS0tLS0tLQorICEoICggMSB8IDIgKSApICYgMworKDEgcm93KQorCitTRUxFQ1QgJyJo
ZWxsbyB3b3JsZCIgfCBmb28nOjphbnlxdWVyeTo6dGV4dDsKKyAgICAgICAgdGV4dCAgICAgICAg
IAorLS0tLS0tLS0tLS0tLS0tLS0tLS0tCisgImhlbGxvIHdvcmxkIiB8IGZvbworKDEgcm93KQor
CitTRUxFQ1QgYW55cXVlcnlfcXVlcnl0cmVlKCcxICYgMiB8IDMnOjphbnlxdWVyeSk7CisgYW55
cXVlcnlfcXVlcnl0cmVlIAorLS0tLS0tLS0tLS0tLS0tLS0tLS0KKyAxIDIgJiAzIHwKKygxIHJv
dykKKworLS0gaW50OCBtYXRjaGluZworU0VMRUNUIEFSUkFZWzEsMiwzXTo6aW50OFtdIEBAICcx
Jzo6YW55cXVlcnk7CisgP2NvbHVtbj8gCistLS0tLS0tLS0tCisgdAorKDEgcm93KQorCitTRUxF
Q1QgQVJSQVlbMSwyLDNdOjppbnQ4W10gQEAgJzEgJiAyJzo6YW55cXVlcnk7CisgP2NvbHVtbj8g
CistLS0tLS0tLS0tCisgdAorKDEgcm93KQorCitTRUxFQ1QgQVJSQVlbMSwyLDNdOjppbnQ4W10g
QEAgJzEgJiA0Jzo6YW55cXVlcnk7CisgP2NvbHVtbj8gCistLS0tLS0tLS0tCisgZgorKDEgcm93
KQorCitTRUxFQ1QgQVJSQVlbMSwyLDNdOjppbnQ4W10gQEAgJzEgfCA0Jzo6YW55cXVlcnk7Cisg
P2NvbHVtbj8gCistLS0tLS0tLS0tCisgdAorKDEgcm93KQorCitTRUxFQ1QgQVJSQVlbMSwyLDNd
OjppbnQ4W10gQEAgJyE0Jzo6YW55cXVlcnk7CisgP2NvbHVtbj8gCistLS0tLS0tLS0tCisgdAor
KDEgcm93KQorCitTRUxFQ1QgQVJSQVlbMSwyLDNdOjppbnQ4W10gQEAgJyExJzo6YW55cXVlcnk7
CisgP2NvbHVtbj8gCistLS0tLS0tLS0tCisgZgorKDEgcm93KQorCitTRUxFQ1QgQVJSQVlbMSwy
LDNdOjppbnQ4W10gQEAgJyE0ICYgMSc6OmFueXF1ZXJ5OworID9jb2x1bW4/IAorLS0tLS0tLS0t
LQorIHQKKygxIHJvdykKKworU0VMRUNUIEFSUkFZWzEsMiwzXTo6aW50OFtdIEBAICcoMSB8IDQp
ICYgKDIgfCA1KSc6OmFueXF1ZXJ5OworID9jb2x1bW4/IAorLS0tLS0tLS0tLQorIHQKKygxIHJv
dykKKworLS0gY29tbXV0YXRvcgorU0VMRUNUICcxICYgMic6OmFueXF1ZXJ5IH5+IEFSUkFZWzEs
MiwzXTo6aW50OFtdOworID9jb2x1bW4/IAorLS0tLS0tLS0tLQorIHQKKygxIHJvdykKKworU0VM
RUNUICcxICYgNCc6OmFueXF1ZXJ5IH5+IEFSUkFZWzEsMiwzXTo6aW50OFtdOworID9jb2x1bW4/
IAorLS0tLS0tLS0tLQorIGYKKygxIHJvdykKKworLS0gdXVpZAorU0VMRUNUIEFSUkFZWycwMDAw
MDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDEnOjp1dWlkLAorICAgICAgICAgICAgICcw
MDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDInXQorICAgICAgIEBAICcwMDAwMDAw
MC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDEgJiAwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0w
MDAwMDAwMDAwMDInOjphbnlxdWVyeTsKKyA/Y29sdW1uPyAKKy0tLS0tLS0tLS0KKyB0CisoMSBy
b3cpCisKK1NFTEVDVCBBUlJBWVsnMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAx
Jzo6dXVpZF0KKyAgICAgICBAQCAnMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAy
Jzo6YW55cXVlcnk7CisgP2NvbHVtbj8gCistLS0tLS0tLS0tCisgZgorKDEgcm93KQorCistLSB0
ZXh0CitTRUxFQ1QgQVJSQVlbJ2FwcGxlJywnYmFuYW5hJywnY2hlcnJ5J106OnRleHRbXSBAQCAn
YXBwbGUgJiBiYW5hbmEnOjphbnlxdWVyeTsKKyA/Y29sdW1uPyAKKy0tLS0tLS0tLS0KKyB0Ciso
MSByb3cpCisKK1NFTEVDVCBBUlJBWVsnYXBwbGUnLCdiYW5hbmEnLCdjaGVycnknXTo6dGV4dFtd
IEBAICciYmFuYW5hIiB8IGdyYXBlJzo6YW55cXVlcnk7CisgP2NvbHVtbj8gCistLS0tLS0tLS0t
CisgdAorKDEgcm93KQorCitTRUxFQ1QgQVJSQVlbJ2FwcGxlJywnYmFuYW5hJywnY2hlcnJ5J106
OnRleHRbXSBAQCAnZHVyaWFuIHwgZ3JhcGUnOjphbnlxdWVyeTsKKyA/Y29sdW1uPyAKKy0tLS0t
LS0tLS0KKyBmCisoMSByb3cpCisKKy0tIGVtcHR5IGFycmF5CitTRUxFQ1QgQVJSQVlbXTo6aW50
OFtdIEBAICcxJzo6YW55cXVlcnk7CisgP2NvbHVtbj8gCistLS0tLS0tLS0tCisgZgorKDEgcm93
KQorCitTRUxFQ1QgQVJSQVlbXTo6aW50OFtdIEBAICchMSc6OmFueXF1ZXJ5OworID9jb2x1bW4/
IAorLS0tLS0tLS0tLQorIHQKKygxIHJvdykKKworLS0gcGFyc2UgZXJyb3JzCitTRUxFQ1QgJyc6
OmFueXF1ZXJ5OworRVJST1I6ICB1bmV4cGVjdGVkIGVuZCBvZiBpbnB1dCBpbiBhbnlxdWVyeQor
TElORSAxOiBTRUxFQ1QgJyc6OmFueXF1ZXJ5OworICAgICAgICAgICAgICAgXgorU0VMRUNUICcx
ICYnOjphbnlxdWVyeTsKK0VSUk9SOiAgdW5leHBlY3RlZCBlbmQgb2YgaW5wdXQgaW4gYW55cXVl
cnkKK0xJTkUgMTogU0VMRUNUICcxICYnOjphbnlxdWVyeTsKKyAgICAgICAgICAgICAgIF4KK1NF
TEVDVCAnMSAmICgyJzo6YW55cXVlcnk7CitFUlJPUjogIG1pc3NpbmcgY2xvc2luZyBwYXJlbnRo
ZXNpcyBpbiBhbnlxdWVyeQorTElORSAxOiBTRUxFQ1QgJzEgJiAoMic6OmFueXF1ZXJ5OworICAg
ICAgICAgICAgICAgXgorU0VMRUNUICcxICkgMic6OmFueXF1ZXJ5OworRVJST1I6ICB1bmV4cGVj
dGVkIHRyYWlsaW5nIGlucHV0IGluIGFueXF1ZXJ5CitMSU5FIDE6IFNFTEVDVCAnMSApIDInOjph
bnlxdWVyeTsKKyAgICAgICAgICAgICAgIF4KKy0tIHJ1bnRpbWUgZXJyb3JzOiB0b2tlbiBjYW5u
b3QgYmUgcGFyc2VkIGFzIGVsZW1lbnQgdHlwZQorU0VMRUNUIEFSUkFZWzEsMl06OmludDhbXSBA
QCAnYWJjJzo6YW55cXVlcnk7CitFUlJPUjogIGludmFsaWQgaW5wdXQgc3ludGF4IGZvciB0eXBl
IGJpZ2ludDogImFiYyIKKy0tCistLSBQaGFzZSAzOiBHaVNUIHNpZ25hdHVyZSBpbmRleAorLS0K
Ky0tIGFtdmFsaWRhdGU6IHdlbGwtZm9ybWVkIG9wY2xhc3MKK1NFTEVDVCBhbW5hbWUsIG9wY25h
bWUgRlJPTSBwZ19vcGNsYXNzIG9wYworTEVGVCBKT0lOIHBnX2FtIGFtIE9OIGFtLm9pZCA9IG9w
Y21ldGhvZAorV0hFUkUgb3BjLm9wY25hbWUgPSAnYW55YXJyYXlfZ2lzdF9vcHMnIEFORCBOT1Qg
YW12YWxpZGF0ZShvcGMub2lkKTsKKyBhbW5hbWUgfCBvcGNuYW1lIAorLS0tLS0tLS0rLS0tLS0t
LS0tCisoMCByb3dzKQorCistLSBpbnQ4IEdpU1Q6IGJ1aWxkIGRldGVybWluaXN0aWMgdGFibGUK
K0NSRUFURSBUQUJMRSBhbnlhcnJheV9naXN0X2ludDggKGlkIGludCwgYSBpbnQ4W10pOworSU5T
RVJUIElOVE8gYW55YXJyYXlfZ2lzdF9pbnQ4IFZBTFVFUworICAoMSwgQVJSQVlbMSwyLDNdOjpp
bnQ4W10pLAorICAoMiwgQVJSQVlbMTAsMjAsMzBdOjppbnQ4W10pLAorICAoMywgQVJSQVlbMTAs
MjAsMzBdOjppbnQ4W10pLAorICAoNCwgQVJSQVlbMSwyLDMsNCw1XTo6aW50OFtdKSwKKyAgKDUs
IEFSUkFZWzEwMCwyMDBdOjppbnQ4W10pOworQ1JFQVRFIElOREVYIGFueWFycmF5X2dpc3RfaW50
OF9pZHgKKyAgT04gYW55YXJyYXlfZ2lzdF9pbnQ4IFVTSU5HIGdpc3QoYSBhbnlhcnJheV9naXN0
X29wcyk7CitTRVQgZW5hYmxlX3NlcXNjYW4gPSBvZmY7CitTRUxFQ1QgaWQgRlJPTSBhbnlhcnJh
eV9naXN0X2ludDggV0hFUkUgYSBAPiBBUlJBWVsxLDJdOjppbnQ4W10gT1JERVIgQlkgaWQ7Cisg
aWQgCistLS0tCisgIDEKKyAgNAorKDIgcm93cykKKworU0VMRUNUIGlkIEZST00gYW55YXJyYXlf
Z2lzdF9pbnQ4IFdIRVJFIGEgJiYgQVJSQVlbMTAsMjAwXTo6aW50OFtdIE9SREVSIEJZIGlkOwor
IGlkIAorLS0tLQorICAyCisgIDMKKyAgNQorKDMgcm93cykKKworU0VMRUNUIGlkIEZST00gYW55
YXJyYXlfZ2lzdF9pbnQ4IFdIRVJFIGEgPSBBUlJBWVsxMCwyMCwzMF06OmludDhbXSBPUkRFUiBC
WSBpZDsKKyBpZCAKKy0tLS0KKyAgMgorICAzCisoMiByb3dzKQorCitTRUxFQ1QgaWQgRlJPTSBh
bnlhcnJheV9naXN0X2ludDggV0hFUkUgYSA8QCBBUlJBWVsxLDIsMyw0LDVdOjppbnQ4W10gT1JE
RVIgQlkgaWQ7CisgaWQgCistLS0tCisgIDEKKyAgNAorKDIgcm93cykKKworU0VMRUNUIGlkIEZS
T00gYW55YXJyYXlfZ2lzdF9pbnQ4IFdIRVJFIGEgQEAgJzEwICYgMjAnOjphbnlxdWVyeSBPUkRF
UiBCWSBpZDsKKyBpZCAKKy0tLS0KKyAgMgorICAzCisoMiByb3dzKQorCitTRUxFQ1QgaWQgRlJP
TSBhbnlhcnJheV9naXN0X2ludDggV0hFUkUgYSBAQCAnMSB8IDEwMCc6OmFueXF1ZXJ5IE9SREVS
IEJZIGlkOworIGlkIAorLS0tLQorICAxCisgIDQKKyAgNQorKDMgcm93cykKKworU0VMRUNUIGlk
IEZST00gYW55YXJyYXlfZ2lzdF9pbnQ4IFdIRVJFIGEgQEAgJyExICYgMTAnOjphbnlxdWVyeSBP
UkRFUiBCWSBpZDsKKyBpZCAKKy0tLS0KKyAgMgorICAzCisoMiByb3dzKQorCistLSByZXN1bHQg
Y29uc2lzdGVuY3k6IEdpU1QgbXVzdCBhZ3JlZSB3aXRoIHNlcXNjYW4KK1NFTEVDVCAoCisgIFNF
TEVDVCBjb3VudCgqKSBGUk9NIGFueWFycmF5X2dpc3RfaW50OCBXSEVSRSBhIEA+IEFSUkFZWzEw
XTo6aW50OFtdCispID0gKAorICBTRUxFQ1QgY291bnQoKikgRlJPTSAoU0VMRUNUIDEgRlJPTSBh
bnlhcnJheV9naXN0X2ludDggV0hFUkUgYSBAPiBBUlJBWVsxMF06OmludDhbXSkgcworKSBBUyBn
aXN0X21hdGNoZXNfc2Vxc2NhbjsKKyBnaXN0X21hdGNoZXNfc2Vxc2NhbiAKKy0tLS0tLS0tLS0t
LS0tLS0tLS0tLS0KKyB0CisoMSByb3cpCisKK1JFU0VUIGVuYWJsZV9zZXFzY2FuOworLS0gdGV4
dCBHaVNUCitDUkVBVEUgVEFCTEUgYW55YXJyYXlfZ2lzdF90ZXh0IChpZCBpbnQsIGEgdGV4dFtd
KTsKK0lOU0VSVCBJTlRPIGFueWFycmF5X2dpc3RfdGV4dCBWQUxVRVMKKyAgKDEsIEFSUkFZWydh
cHBsZScsJ2JhbmFuYSddKSwKKyAgKDIsIEFSUkFZWydiYW5hbmEnLCdjaGVycnknXSksCisgICgz
LCBBUlJBWVsnYXBwbGUnLCdjaGVycnknLCdkdXJpYW4nXSk7CitDUkVBVEUgSU5ERVggYW55YXJy
YXlfZ2lzdF90ZXh0X2lkeAorICBPTiBhbnlhcnJheV9naXN0X3RleHQgVVNJTkcgZ2lzdChhIGFu
eWFycmF5X2dpc3Rfb3BzKHNpZ2xlbj02NCkpOworU0VUIGVuYWJsZV9zZXFzY2FuID0gb2ZmOwor
U0VMRUNUIGlkIEZST00gYW55YXJyYXlfZ2lzdF90ZXh0IFdIRVJFIGEgQD4gQVJSQVlbJ2FwcGxl
J106OnRleHRbXSBPUkRFUiBCWSBpZDsKKyBpZCAKKy0tLS0KKyAgMQorICAzCisoMiByb3dzKQor
CitTRUxFQ1QgaWQgRlJPTSBhbnlhcnJheV9naXN0X3RleHQgV0hFUkUgYSBAQCAnYXBwbGUgJiBj
aGVycnknOjphbnlxdWVyeSBPUkRFUiBCWSBpZDsKKyBpZCAKKy0tLS0KKyAgMworKDEgcm93KQor
CitSRVNFVCBlbmFibGVfc2Vxc2NhbjsKKy0tIHNpZ2xlbiBib3VuZHMKK0NSRUFURSBJTkRFWCBP
TiBhbnlhcnJheV9naXN0X3RleHQgVVNJTkcgZ2lzdChhIGFueWFycmF5X2dpc3Rfb3BzKHNpZ2xl
bj0wKSk7CitFUlJPUjogIHZhbHVlIDAgb3V0IG9mIGJvdW5kcyBmb3Igb3B0aW9uICJzaWdsZW4i
CitERVRBSUw6ICBWYWxpZCB2YWx1ZXMgYXJlIGJldHdlZW4gIjEiIGFuZCAiMjAyNCIuCitDUkVB
VEUgSU5ERVggT04gYW55YXJyYXlfZ2lzdF90ZXh0IFVTSU5HIGdpc3QoYSBhbnlhcnJheV9naXN0
X29wcyhzaWdsZW49ODE5MykpOworRVJST1I6ICB2YWx1ZSA4MTkzIG91dCBvZiBib3VuZHMgZm9y
IG9wdGlvbiAic2lnbGVuIgorREVUQUlMOiAgVmFsaWQgdmFsdWVzIGFyZSBiZXR3ZWVuICIxIiBh
bmQgIjIwMjQiLgorLS0KKy0tIFBoYXNlIDQ6IEdJTiBpbmRleCAocGVyLXR5cGUsIHN1cHBvcnRz
IHN0YW5kYXJkIG9wcyArIEBAKQorLS0KKy0tIGFtdmFsaWRhdGU6IGFsbCB0aHJlZSBvcGNsYXNz
ZXMKK1NFTEVDVCBhbW5hbWUsIG9wY25hbWUgRlJPTSBwZ19vcGNsYXNzIG9wYworTEVGVCBKT0lO
IHBnX2FtIGFtIE9OIGFtLm9pZCA9IG9wY21ldGhvZAorV0hFUkUgb3BjLm9wY25hbWUgTElLRSAn
JWFueXF1ZXJ5X2dpbl9vcHMnIEFORCBOT1QgYW12YWxpZGF0ZShvcGMub2lkKTsKKyBhbW5hbWUg
fCBvcGNuYW1lIAorLS0tLS0tLS0rLS0tLS0tLS0tCisoMCByb3dzKQorCistLSBpbnQ4IEdJTgor
Q1JFQVRFIFRBQkxFIGFueWFycmF5X2dpbl9pbnQ4IChpZCBpbnQsIGEgaW50OFtdKTsKK0lOU0VS
VCBJTlRPIGFueWFycmF5X2dpbl9pbnQ4IFZBTFVFUworICAoMSwgQVJSQVlbMSwyLDNdOjppbnQ4
W10pLAorICAoMiwgQVJSQVlbMTAsMjAsMzBdOjppbnQ4W10pLAorICAoMywgQVJSQVlbMTAsMjAs
MzBdOjppbnQ4W10pLAorICAoNCwgQVJSQVlbMSwyLDMsNCw1XTo6aW50OFtdKSwKKyAgKDUsIEFS
UkFZWzEwMCwyMDBdOjppbnQ4W10pOworQ1JFQVRFIElOREVYIGFueWFycmF5X2dpbl9pbnQ4X2lk
eAorICBPTiBhbnlhcnJheV9naW5faW50OCBVU0lORyBnaW4oYSBpbnQ4X2FueXF1ZXJ5X2dpbl9v
cHMpOworU0VUIGVuYWJsZV9zZXFzY2FuID0gb2ZmOworU0VMRUNUIGlkIEZST00gYW55YXJyYXlf
Z2luX2ludDggV0hFUkUgYSBAPiBBUlJBWVsxLDJdOjppbnQ4W10gT1JERVIgQlkgaWQ7CisgaWQg
CistLS0tCisgIDEKKyAgNAorKDIgcm93cykKKworU0VMRUNUIGlkIEZST00gYW55YXJyYXlfZ2lu
X2ludDggV0hFUkUgYSAmJiBBUlJBWVsxMCwyMDBdOjppbnQ4W10gT1JERVIgQlkgaWQ7CisgaWQg
CistLS0tCisgIDIKKyAgMworICA1CisoMyByb3dzKQorCitTRUxFQ1QgaWQgRlJPTSBhbnlhcnJh
eV9naW5faW50OCBXSEVSRSBhIEBAICcxMCAmIDIwJzo6YW55cXVlcnkgT1JERVIgQlkgaWQ7Cisg
aWQgCistLS0tCisgIDIKKyAgMworKDIgcm93cykKKworU0VMRUNUIGlkIEZST00gYW55YXJyYXlf
Z2luX2ludDggV0hFUkUgYSBAQCAnKDEgJiAyKSB8IDEwMCc6OmFueXF1ZXJ5IE9SREVSIEJZIGlk
OworIGlkIAorLS0tLQorICAxCisgIDQKKyAgNQorKDMgcm93cykKKworU0VMRUNUIGlkIEZST00g
YW55YXJyYXlfZ2luX2ludDggV0hFUkUgYSBAQCAnITEnOjphbnlxdWVyeSBPUkRFUiBCWSBpZDsK
KyBpZCAKKy0tLS0KKyAgMgorICAzCisgIDUKKygzIHJvd3MpCisKKy0tIHV1aWQgR0lOCitDUkVB
VEUgVEFCTEUgYW55YXJyYXlfZ2luX3V1aWQgKGlkIGludCwgYSB1dWlkW10pOworSU5TRVJUIElO
VE8gYW55YXJyYXlfZ2luX3V1aWQgVkFMVUVTCisgICgxLCBBUlJBWVsnMTExMTExMTEtMTExMS0x
MTExLTExMTEtMTExMTExMTExMTExJzo6dXVpZCwKKyAgICAgICAgICAgICcyMjIyMjIyMi0yMjIy
LTIyMjItMjIyMi0yMjIyMjIyMjIyMjInXSksCisgICgyLCBBUlJBWVsnMzMzMzMzMzMtMzMzMy0z
MzMzLTMzMzMtMzMzMzMzMzMzMzMzJzo6dXVpZF0pLAorICAoMywgQVJSQVlbJzExMTExMTExLTEx
MTEtMTExMS0xMTExLTExMTExMTExMTExMSc6OnV1aWQsCisgICAgICAgICAgICAnMzMzMzMzMzMt
MzMzMy0zMzMzLTMzMzMtMzMzMzMzMzMzMzMzJ10pOworQ1JFQVRFIElOREVYIGFueWFycmF5X2dp
bl91dWlkX2lkeAorICBPTiBhbnlhcnJheV9naW5fdXVpZCBVU0lORyBnaW4oYSB1dWlkX2FueXF1
ZXJ5X2dpbl9vcHMpOworU0VUIGVuYWJsZV9zZXFzY2FuID0gb2ZmOworU0VMRUNUIGlkIEZST00g
YW55YXJyYXlfZ2luX3V1aWQKKyAgV0hFUkUgYSBAQCAnMTExMTExMTEtMTExMS0xMTExLTExMTEt
MTExMTExMTExMTExICYgMjIyMjIyMjItMjIyMi0yMjIyLTIyMjItMjIyMjIyMjIyMjIyJzo6YW55
cXVlcnkKKyAgT1JERVIgQlkgaWQ7CisgaWQgCistLS0tCisgIDEKKygxIHJvdykKKworU0VMRUNU
IGlkIEZST00gYW55YXJyYXlfZ2luX3V1aWQKKyAgV0hFUkUgYSBAPiBBUlJBWVsnMTExMTExMTEt
MTExMS0xMTExLTExMTEtMTExMTExMTExMTExJzo6dXVpZF0KKyAgT1JERVIgQlkgaWQ7CisgaWQg
CistLS0tCisgIDEKKyAgMworKDIgcm93cykKKworUkVTRVQgZW5hYmxlX3NlcXNjYW47CistLSB0
ZXh0IEdJTgorQ1JFQVRFIFRBQkxFIGFueWFycmF5X2dpbl90ZXh0IChpZCBpbnQsIGEgdGV4dFtd
KTsKK0lOU0VSVCBJTlRPIGFueWFycmF5X2dpbl90ZXh0IFZBTFVFUworICAoMSwgQVJSQVlbJ2Fw
cGxlJywnYmFuYW5hJ10pLAorICAoMiwgQVJSQVlbJ2JhbmFuYScsJ2NoZXJyeSddKSwKKyAgKDMs
IEFSUkFZWydhcHBsZScsJ2NoZXJyeScsJ2R1cmlhbiddKTsKK0NSRUFURSBJTkRFWCBhbnlhcnJh
eV9naW5fdGV4dF9pZHgKKyAgT04gYW55YXJyYXlfZ2luX3RleHQgVVNJTkcgZ2luKGEgdGV4dF9h
bnlxdWVyeV9naW5fb3BzKTsKK1NFVCBlbmFibGVfc2Vxc2NhbiA9IG9mZjsKK1NFTEVDVCBpZCBG
Uk9NIGFueWFycmF5X2dpbl90ZXh0IFdIRVJFIGEgQEAgJ2FwcGxlICYgY2hlcnJ5Jzo6YW55cXVl
cnkgT1JERVIgQlkgaWQ7CisgaWQgCistLS0tCisgIDMKKygxIHJvdykKKworU0VMRUNUIGlkIEZS
T00gYW55YXJyYXlfZ2luX3RleHQgV0hFUkUgYSBAQCAnImR1cmlhbiInOjphbnlxdWVyeSBPUkRF
UiBCWSBpZDsKKyBpZCAKKy0tLS0KKyAgMworKDEgcm93KQorCitTRUxFQ1QgaWQgRlJPTSBhbnlh
cnJheV9naW5fdGV4dCBXSEVSRSBhIEBAICdhcHBsZSB8IGdyYXBlJzo6YW55cXVlcnkgT1JERVIg
QlkgaWQ7CisgaWQgCistLS0tCisgIDEKKyAgMworKDIgcm93cykKKworU0VMRUNUIGlkIEZST00g
YW55YXJyYXlfZ2luX3RleHQgV0hFUkUgYSBAQCAnIWJhbmFuYSc6OmFueXF1ZXJ5IE9SREVSIEJZ
IGlkOworIGlkIAorLS0tLQorICAzCisoMSByb3cpCisKK1JFU0VUIGVuYWJsZV9zZXFzY2FuOwor
LS0KKy0tIFBoYXNlIDU6IGNyb3NzLUFNIGNvbnNpc3RlbmN5IGFuZCBlZGdlIGNhc2VzCistLQor
LS0gQnVpbGQgYSBsYXJnZXIgZGV0ZXJtaW5pc3RpYyBpbnQ4IHRhYmxlIGFuZCBpbmRleCBpdCB3
aXRoIGJvdGggR2lTVCBhbmQKKy0tIEdJTi4gIFRoZW4gcnVuIGVhY2ggY2FuZGlkYXRlIHF1ZXJ5
IHVuZGVyIHNlcXNjYW4sIEdpU1QgYW5kIEdJTiBhbmQgY2hlY2sKKy0tIHRoYXQgYWxsIHRocmVl
IHBsYW5zIHJldHVybiB0aGUgc2FtZSByb3cgc2V0LgorLS0KK0NSRUFURSBUQUJMRSBhbnlhcnJh
eV94Y2hlY2sgKGlkIGludCwgYSBpbnQ4W10pOworSU5TRVJUIElOVE8gYW55YXJyYXlfeGNoZWNr
CitTRUxFQ1QgZywKKyAgICAgICBBUlJBWVsoZyAlIDcpOjppbnQ4LCAoKGcgKiAzKSAlIDExKTo6
aW50OCwgKChnICsgMSkgJSA1KTo6aW50OF0KK0ZST00gZ2VuZXJhdGVfc2VyaWVzKDEsIDIwMCkg
ZzsKKy0tIGEgZmV3IGhhbmQtcGlja2VkIHJvd3MgdG8gZXhlcmNpc2UgY29tbW9uIHZhbHVlcwor
SU5TRVJUIElOVE8gYW55YXJyYXlfeGNoZWNrIFZBTFVFUworICAoMTAwMSwgQVJSQVlbMSwyLDMs
NCw1XTo6aW50OFtdKSwKKyAgKDEwMDIsIEFSUkFZWzEsMiwzLDQsNV06OmludDhbXSksCisgICgx
MDAzLCBBUlJBWVsxMDAsMjAwLDMwMF06OmludDhbXSksCisgICgxMDA0LCBBUlJBWVtdOjppbnQ4
W10pLAorICAoMTAwNSwgTlVMTCk7CitDUkVBVEUgSU5ERVggYW55YXJyYXlfeGNoZWNrX2dpc3Qg
T04gYW55YXJyYXlfeGNoZWNrCisgIFVTSU5HIGdpc3QoYSBhbnlhcnJheV9naXN0X29wcyk7CitD
UkVBVEUgSU5ERVggYW55YXJyYXlfeGNoZWNrX2dpbiBPTiBhbnlhcnJheV94Y2hlY2sKKyAgVVNJ
TkcgZ2luKGEgaW50OF9hbnlxdWVyeV9naW5fb3BzKTsKKy0tIFJ1biBlYWNoIHByZWRpY2F0ZSB0
aHJlZSB0aW1lczogcHVyZSBzZXFzY2FuLCBHaVNULW9ubHksIEdJTi1vbmx5LgorLS0gQWxsIHRo
cmVlIHJlc3VsdCBzZXRzIG11c3QgbWF0Y2guCitDUkVBVEUgRlVOQ1RJT04gYW55YXJyYXlfeGNo
ZWNrX21hdGNoKHByZWQgdGV4dCkKK1JFVFVSTlMgVEFCTEUoZ2lzdF9vayBib29sLCBnaW5fb2sg
Ym9vbCkKK0xBTkdVQUdFIHBscGdzcWwgQVMgJCQKK0RFQ0xBUkUKKyAgc2VxIGludFtdOyBnc3Qg
aW50W107IGdpbiBpbnRbXTsKK0JFR0lOCisgIFNFVCBMT0NBTCBlbmFibGVfc2Vxc2NhbiA9IG9u
OworICBTRVQgTE9DQUwgZW5hYmxlX2luZGV4c2NhbiA9IG9mZjsKKyAgU0VUIExPQ0FMIGVuYWJs
ZV9iaXRtYXBzY2FuID0gb2ZmOworICBFWEVDVVRFICdTRUxFQ1QgYXJyYXlfYWdnKGlkIE9SREVS
IEJZIGlkKSBGUk9NIGFueWFycmF5X3hjaGVjayBXSEVSRSAnCisgICAgICAgICAgfHwgcHJlZCBJ
TlRPIHNlcTsKKworICAtLSBGb3JjZSBHaVNUIGJ5IGhpZGluZyB0aGUgR0lOIGluZGV4LgorICBB
TFRFUiBJTkRFWCBhbnlhcnJheV94Y2hlY2tfZ2luIFNFVCAoZmFzdHVwZGF0ZSA9IG9mZik7Cisg
IFNFVCBMT0NBTCBlbmFibGVfc2Vxc2NhbiA9IG9mZjsKKyAgU0VUIExPQ0FMIGVuYWJsZV9pbmRl
eHNjYW4gPSBvbjsKKyAgU0VUIExPQ0FMIGVuYWJsZV9iaXRtYXBzY2FuID0gb247CisgIERST1Ag
SU5ERVggYW55YXJyYXlfeGNoZWNrX2dpbjsKKyAgRVhFQ1VURSAnU0VMRUNUIGFycmF5X2FnZyhp
ZCBPUkRFUiBCWSBpZCkgRlJPTSBhbnlhcnJheV94Y2hlY2sgV0hFUkUgJworICAgICAgICAgIHx8
IHByZWQgSU5UTyBnc3Q7CisgIENSRUFURSBJTkRFWCBhbnlhcnJheV94Y2hlY2tfZ2luIE9OIGFu
eWFycmF5X3hjaGVjaworICAgIFVTSU5HIGdpbihhIGludDhfYW55cXVlcnlfZ2luX29wcyk7CisK
KyAgLS0gRm9yY2UgR0lOIGJ5IGhpZGluZyBHaVNULgorICBEUk9QIElOREVYIGFueWFycmF5X3hj
aGVja19naXN0OworICBFWEVDVVRFICdTRUxFQ1QgYXJyYXlfYWdnKGlkIE9SREVSIEJZIGlkKSBG
Uk9NIGFueWFycmF5X3hjaGVjayBXSEVSRSAnCisgICAgICAgICAgfHwgcHJlZCBJTlRPIGdpbjsK
KyAgQ1JFQVRFIElOREVYIGFueWFycmF5X3hjaGVja19naXN0IE9OIGFueWFycmF5X3hjaGVjawor
ICAgIFVTSU5HIGdpc3QoYSBhbnlhcnJheV9naXN0X29wcyk7CisKKyAgZ2lzdF9vayA6PSBzZXEg
SVMgTk9UIERJU1RJTkNUIEZST00gZ3N0OworICBnaW5fb2sgIDo9IHNlcSBJUyBOT1QgRElTVElO
Q1QgRlJPTSBnaW47CisgIFJFVFVSTiBORVhUOworRU5EICQkOworU0VMRUNUIHByZWQsIGdpc3Rf
b2ssIGdpbl9vayBGUk9NIChWQUxVRVMKKyAgKCdhIEA+IEFSUkFZWzEsMl06OmludDhbXScpLAor
ICAoJ2EgQD4gQVJSQVlbMTAwLDIwMF06OmludDhbXScpLAorICAoJ2EgJiYgQVJSQVlbNSw5OV06
OmludDhbXScpLAorICAoJ2EgPSBBUlJBWVsxLDIsMyw0LDVdOjppbnQ4W10nKSwKKyAgKCdhIEBA
ICcnMSAmIDInJzo6YW55cXVlcnknKSwKKyAgKCdhIEBAICcnMTAwIHwgOTk5Jyc6OmFueXF1ZXJ5
JyksCisgICgnYSBAQCAnJyExICYgMicnOjphbnlxdWVyeScpCispIHYocHJlZCksIExBVEVSQUwg
YW55YXJyYXlfeGNoZWNrX21hdGNoKHByZWQpOworICAgICAgICAgICAgIHByZWQgICAgICAgICAg
ICAgfCBnaXN0X29rIHwgZ2luX29rIAorLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0t
LS0tLS0tLSstLS0tLS0tLQorIGEgQD4gQVJSQVlbMSwyXTo6aW50OFtdICAgICAgfCB0ICAgICAg
IHwgdAorIGEgQD4gQVJSQVlbMTAwLDIwMF06OmludDhbXSAgfCB0ICAgICAgIHwgdAorIGEgJiYg
QVJSQVlbNSw5OV06OmludDhbXSAgICAgfCB0ICAgICAgIHwgdAorIGEgPSBBUlJBWVsxLDIsMyw0
LDVdOjppbnQ4W10gfCB0ICAgICAgIHwgdAorIGEgQEAgJzEgJiAyJzo6YW55cXVlcnkgICAgICAg
fCB0ICAgICAgIHwgdAorIGEgQEAgJzEwMCB8IDk5OSc6OmFueXF1ZXJ5ICAgfCB0ICAgICAgIHwg
dAorIGEgQEAgJyExICYgMic6OmFueXF1ZXJ5ICAgICAgfCB0ICAgICAgIHwgdAorKDcgcm93cykK
KworLS0gRWRnZSBjYXNlczogZW1wdHkgLyBOVUxMIGFycmF5cyB2aWEgaW5kZXgKK1NFVCBlbmFi
bGVfc2Vxc2NhbiA9IG9mZjsKK1NFTEVDVCBpZCBGUk9NIGFueWFycmF5X3hjaGVjayBXSEVSRSBh
IEA+IEFSUkFZW106OmludDhbXSBBTkQgaWQgPSAxMDA0OworICBpZCAgCistLS0tLS0KKyAxMDA0
CisoMSByb3cpCisKK1NFTEVDVCBpZCBGUk9NIGFueWFycmF5X3hjaGVjayBXSEVSRSBhIDxAIEFS
UkFZWzEsMiwzXTo6aW50OFtdIEFORCBpZCA8IDEwMCBPUkRFUiBCWSBpZCBMSU1JVCAzOworIGlk
IAorLS0tLQorICAxCisgMTUKKyAzMAorKDMgcm93cykKKworU0VMRUNUIGNvdW50KCopIEZST00g
YW55YXJyYXlfeGNoZWNrIFdIRVJFIGEgSVMgTlVMTDsKKyBjb3VudCAKKy0tLS0tLS0KKyAgICAg
MQorKDEgcm93KQorCitSRVNFVCBlbmFibGVfc2Vxc2NhbjsKKy0tIERFTEVURSAvIFZBQ1VVTSAv
IHJlLXF1ZXJ5IHRocm91Z2ggaW5kZXgKK0RFTEVURSBGUk9NIGFueWFycmF5X3hjaGVjayBXSEVS
RSBpZCBCRVRXRUVOIDEgQU5EIDUwOworVkFDVVVNIGFueWFycmF5X3hjaGVjazsKK1NFVCBlbmFi
bGVfc2Vxc2NhbiA9IG9mZjsKK1NFTEVDVCBjb3VudCgqKSBGUk9NIGFueWFycmF5X3hjaGVjayBX
SEVSRSBhIEBAICcxIHwgMic6OmFueXF1ZXJ5OworIGNvdW50IAorLS0tLS0tLQorICAgIDk4Ciso
MSByb3cpCisKK1JFU0VUIGVuYWJsZV9zZXFzY2FuOworRFJPUCBGVU5DVElPTiBhbnlhcnJheV94
Y2hlY2tfbWF0Y2godGV4dCk7CmRpZmYgLS1naXQgYS9jb250cmliL2FueWFycmF5L21lc29uLmJ1
aWxkIGIvY29udHJpYi9hbnlhcnJheS9tZXNvbi5idWlsZApuZXcgZmlsZSBtb2RlIDEwMDY0NApp
bmRleCAwMDAwMDAwMDAwMC4uYTIwNjQ2YjgyYjIKLS0tIC9kZXYvbnVsbAorKysgYi9jb250cmli
L2FueWFycmF5L21lc29uLmJ1aWxkCkBAIC0wLDAgKzEsMzggQEAKKyMgQ29weXJpZ2h0IChjKSAy
MDI2LCBQb3N0Z3JlU1FMIEdsb2JhbCBEZXZlbG9wbWVudCBHcm91cAorCithbnlhcnJheV9zb3Vy
Y2VzID0gZmlsZXMoCisgICdhbnlhcnJheS5jJywKKyAgJ2FueWFycmF5X2Jvb2wuYycsCisgICdh
bnlhcnJheV9naW4uYycsCisgICdhbnlhcnJheV9naXN0LmMnLAorICAnYW55YXJyYXlfb3AuYycs
CispCisKK2lmIGhvc3Rfc3lzdGVtID09ICd3aW5kb3dzJworICBhbnlhcnJheV9zb3VyY2VzICs9
IHJjX2xpYl9nZW4ucHJvY2Vzcyh3aW4zMnZlcl9yYywgZXh0cmFfYXJnczogWworICAgICctLU5B
TUUnLCAnYW55YXJyYXknLAorICAgICctLUZJTEVERVNDJywgJ2FueWFycmF5IC0gb3BlcmF0aW9u
cyBhbmQgaW5kZXhlcyBmb3IgYXJyYXlzIG9mIGFueSB0eXBlJyxdKQorZW5kaWYKKworYW55YXJy
YXkgPSBzaGFyZWRfbW9kdWxlKCdhbnlhcnJheScsCisgIGFueWFycmF5X3NvdXJjZXMsCisgIGt3
YXJnczogY29udHJpYl9tb2RfYXJncywKKykKK2NvbnRyaWJfdGFyZ2V0cyArPSBhbnlhcnJheQor
CitpbnN0YWxsX2RhdGEoCisgICdhbnlhcnJheS0tMS4wLnNxbCcsCisgICdhbnlhcnJheS5jb250
cm9sJywKKyAga3dhcmdzOiBjb250cmliX2RhdGFfYXJncywKKykKKwordGVzdHMgKz0geworICAn
bmFtZSc6ICdhbnlhcnJheScsCisgICdzZCc6IG1lc29uLmN1cnJlbnRfc291cmNlX2RpcigpLAor
ICAnYmQnOiBtZXNvbi5jdXJyZW50X2J1aWxkX2RpcigpLAorICAncmVncmVzcyc6IHsKKyAgICAn
c3FsJzogWworICAgICAgJ2FueWFycmF5JywKKyAgICBdLAorICB9LAorfQpkaWZmIC0tZ2l0IGEv
Y29udHJpYi9hbnlhcnJheS9zcWwvYW55YXJyYXkuc3FsIGIvY29udHJpYi9hbnlhcnJheS9zcWwv
YW55YXJyYXkuc3FsCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAwMDAwLi45MGNj
MDYxZmJkZQotLS0gL2Rldi9udWxsCisrKyBiL2NvbnRyaWIvYW55YXJyYXkvc3FsL2FueWFycmF5
LnNxbApAQCAtMCwwICsxLDMzMCBAQAorQ1JFQVRFIEVYVEVOU0lPTiBhbnlhcnJheTsKKworLS0K
Ky0tIFBoYXNlIDE6IHNldCBvcGVyYXRpb25zLCBoZWxwZXJzIGFuZCBvcGVyYXRvcnMgZm9yIGlu
dDgsIHV1aWQsIHRleHQKKy0tCisKKy0tID09PT09IGludDggPT09PT0KK1NFTEVDVCBhbnlhcnJh
eV9zb3J0KEFSUkFZWzMsIDEsIDIsIDFdOjppbnQ4W10pOworU0VMRUNUIGFueWFycmF5X3NvcnQo
QVJSQVlbMywgMSwgMiwgMV06OmludDhbXSwgJ2Rlc2MnKTsKK1NFTEVDVCBhbnlhcnJheV9zb3J0
KEFSUkFZW106OmludDhbXSk7CitTRUxFQ1QgYW55YXJyYXlfdW5pcShBUlJBWVsxLCAxLCAyLCAz
LCAzLCAyXTo6aW50OFtdKTsKK1NFTEVDVCBhbnlhcnJheV9pZHgoQVJSQVlbMTAsIDIwLCAzMF06
OmludDhbXSwgMjA6OmludDgpOworU0VMRUNUIGFueWFycmF5X2lkeChBUlJBWVsxMCwgMjAsIDMw
XTo6aW50OFtdLCA5OTo6aW50OCk7CitTRUxFQ1QgYW55YXJyYXlfc3ViYXJyYXkoQVJSQVlbMSwy
LDMsNCw1XTo6aW50OFtdLCAyLCAyKTsKK1NFTEVDVCBhbnlhcnJheV9zdWJhcnJheShBUlJBWVsx
LDIsMyw0LDVdOjppbnQ4W10sIDMpOworU0VMRUNUIGFueWFycmF5X3N1YmFycmF5KEFSUkFZWzEs
MiwzXTo6aW50OFtdLCA1LCAxKTsKKworU0VMRUNUIEFSUkFZWzEsMiwzXTo6aW50OFtdICYgQVJS
QVlbMiwzLDRdOjppbnQ4W107CitTRUxFQ1QgQVJSQVlbMSwyLDNdOjppbnQ4W10gfCBBUlJBWVsz
LDQsNV06OmludDhbXTsKK1NFTEVDVCBBUlJBWVsxLDIsM106OmludDhbXSB8IDQ6OmludDg7CitT
RUxFQ1QgQVJSQVlbMSwyLDMsNF06OmludDhbXSAtIEFSUkFZWzIsNF06OmludDhbXTsKK1NFTEVD
VCBBUlJBWVsxLDIsMiwzLDJdOjppbnQ4W10gLSAyOjppbnQ4OworU0VMRUNUICMgQVJSQVlbMTAs
MjAsMzBdOjppbnQ4W107CitTRUxFQ1QgQVJSQVlbMTAsMjAsMzBdOjppbnQ4W10gIyAyMDo6aW50
ODsKKworLS0gPT09PT0gdXVpZCA9PT09PQorU0VMRUNUIGFueWFycmF5X3NvcnQoQVJSQVlbCisg
ICcwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDMnOjp1dWlkLAorICAnMDAwMDAw
MDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAxJywKKyAgJzAwMDAwMDAwLTAwMDAtMDAwMC0w
MDAwLTAwMDAwMDAwMDAwMiddKTsKK1NFTEVDVCBhbnlhcnJheV91bmlxKEFSUkFZWworICAnMDAw
MDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAxJzo6dXVpZCwKKyAgJzAwMDAwMDAwLTAw
MDAtMDAwMC0wMDAwLTAwMDAwMDAwMDAwMScsCisgICcwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0w
MDAwMDAwMDAwMDInXSk7CitTRUxFQ1QgYW55YXJyYXlfaWR4KEFSUkFZWworICAnMDAwMDAwMDAt
MDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAxJzo6dXVpZCwKKyAgJzAwMDAwMDAwLTAwMDAtMDAw
MC0wMDAwLTAwMDAwMDAwMDAwMiddLAorICAnMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAw
MDAwMDAyJzo6dXVpZCk7CisKK1NFTEVDVCBBUlJBWVsnMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAt
MDAwMDAwMDAwMDAxJzo6dXVpZCwKKyAgICAgICAgICAgICAnMDAwMDAwMDAtMDAwMC0wMDAwLTAw
MDAtMDAwMDAwMDAwMDAyJ10KKyAgICAgJiBBUlJBWVsnMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAt
MDAwMDAwMDAwMDAyJzo6dXVpZCwKKyAgICAgICAgICAgICAnMDAwMDAwMDAtMDAwMC0wMDAwLTAw
MDAtMDAwMDAwMDAwMDAzJ107CisKK1NFTEVDVCBBUlJBWVsnMDAwMDAwMDAtMDAwMC0wMDAwLTAw
MDAtMDAwMDAwMDAwMDAxJzo6dXVpZF0KKyAgICAgfCAnMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAt
MDAwMDAwMDAwMDAyJzo6dXVpZDsKKworLS0gPT09PT0gdGV4dCA9PT09PQorU0VMRUNUIGFueWFy
cmF5X3NvcnQoQVJSQVlbJ2JhbmFuYScsJ2FwcGxlJywnY2hlcnJ5J10pOworU0VMRUNUIGFueWFy
cmF5X3NvcnQoQVJSQVlbJ2JhbmFuYScsJ2FwcGxlJywnY2hlcnJ5J10sICdkZXNjJyk7CitTRUxF
Q1QgYW55YXJyYXlfdW5pcShBUlJBWVsnYScsJ2InLCdhJywnYycsJ2InXSk7CitTRUxFQ1QgYW55
YXJyYXlfaWR4KEFSUkFZWydhJywnYicsJ2MnXSwgJ2InOjp0ZXh0KTsKK1NFTEVDVCBBUlJBWVsn
YScsJ2InLCdjJ106OnRleHRbXSAmIEFSUkFZWydiJywnYycsJ2QnXTo6dGV4dFtdOworU0VMRUNU
IEFSUkFZWydhJywnYicsJ2MnXTo6dGV4dFtdIHwgJ2QnOjp0ZXh0OworU0VMRUNUIEFSUkFZWydh
JywnYicsJ2MnLCdiJ106OnRleHRbXSAtICdiJzo6dGV4dDsKKworLS0gPT09PT0gZXJyb3IgY2Fz
ZXMgPT09PT0KKy0tIG11bHRpLWRpbQorU0VMRUNUIGFueWFycmF5X3NvcnQoQVJSQVlbWzEsMl0s
WzMsNF1dOjppbnQ4W10pOworLS0gbnVsbHMKK1NFTEVDVCBhbnlhcnJheV9zb3J0KEFSUkFZWzEs
IE5VTEwsIDJdOjppbnQ4W10pOworLS0gYmFkIGRpcmVjdGlvbgorU0VMRUNUIGFueWFycmF5X3Nv
cnQoQVJSQVlbMSwyLDNdOjppbnQ4W10sICdib2d1cycpOworCistLQorLS0gUGhhc2UgMjogYW55
cXVlcnkgYW5kIEBAIG9wZXJhdG9yCistLQorCistLSBwYXJzaW5nICsgb3V0cHV0IHJvdW5kLXRy
aXAKK1NFTEVDVCAnMSAmIDInOjphbnlxdWVyeTo6dGV4dDsKK1NFTEVDVCAnMSAmIDIgfCAzJzo6
YW55cXVlcnk6OnRleHQ7CitTRUxFQ1QgJygxIHwgMikgJiAzJzo6YW55cXVlcnk6OnRleHQ7CitT
RUxFQ1QgJyExICYgMic6OmFueXF1ZXJ5Ojp0ZXh0OworU0VMRUNUICchKDEgfCAyKSAmIDMnOjph
bnlxdWVyeTo6dGV4dDsKK1NFTEVDVCAnImhlbGxvIHdvcmxkIiB8IGZvbyc6OmFueXF1ZXJ5Ojp0
ZXh0OworU0VMRUNUIGFueXF1ZXJ5X3F1ZXJ5dHJlZSgnMSAmIDIgfCAzJzo6YW55cXVlcnkpOwor
CistLSBpbnQ4IG1hdGNoaW5nCitTRUxFQ1QgQVJSQVlbMSwyLDNdOjppbnQ4W10gQEAgJzEnOjph
bnlxdWVyeTsKK1NFTEVDVCBBUlJBWVsxLDIsM106OmludDhbXSBAQCAnMSAmIDInOjphbnlxdWVy
eTsKK1NFTEVDVCBBUlJBWVsxLDIsM106OmludDhbXSBAQCAnMSAmIDQnOjphbnlxdWVyeTsKK1NF
TEVDVCBBUlJBWVsxLDIsM106OmludDhbXSBAQCAnMSB8IDQnOjphbnlxdWVyeTsKK1NFTEVDVCBB
UlJBWVsxLDIsM106OmludDhbXSBAQCAnITQnOjphbnlxdWVyeTsKK1NFTEVDVCBBUlJBWVsxLDIs
M106OmludDhbXSBAQCAnITEnOjphbnlxdWVyeTsKK1NFTEVDVCBBUlJBWVsxLDIsM106OmludDhb
XSBAQCAnITQgJiAxJzo6YW55cXVlcnk7CitTRUxFQ1QgQVJSQVlbMSwyLDNdOjppbnQ4W10gQEAg
JygxIHwgNCkgJiAoMiB8IDUpJzo6YW55cXVlcnk7CisKKy0tIGNvbW11dGF0b3IKK1NFTEVDVCAn
MSAmIDInOjphbnlxdWVyeSB+fiBBUlJBWVsxLDIsM106OmludDhbXTsKK1NFTEVDVCAnMSAmIDQn
OjphbnlxdWVyeSB+fiBBUlJBWVsxLDIsM106OmludDhbXTsKKworLS0gdXVpZAorU0VMRUNUIEFS
UkFZWycwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDEnOjp1dWlkLAorICAgICAg
ICAgICAgICcwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDInXQorICAgICAgIEBA
ICcwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDEgJiAwMDAwMDAwMC0wMDAwLTAw
MDAtMDAwMC0wMDAwMDAwMDAwMDInOjphbnlxdWVyeTsKK1NFTEVDVCBBUlJBWVsnMDAwMDAwMDAt
MDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAxJzo6dXVpZF0KKyAgICAgICBAQCAnMDAwMDAwMDAt
MDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAyJzo6YW55cXVlcnk7CisKKy0tIHRleHQKK1NFTEVD
VCBBUlJBWVsnYXBwbGUnLCdiYW5hbmEnLCdjaGVycnknXTo6dGV4dFtdIEBAICdhcHBsZSAmIGJh
bmFuYSc6OmFueXF1ZXJ5OworU0VMRUNUIEFSUkFZWydhcHBsZScsJ2JhbmFuYScsJ2NoZXJyeSdd
Ojp0ZXh0W10gQEAgJyJiYW5hbmEiIHwgZ3JhcGUnOjphbnlxdWVyeTsKK1NFTEVDVCBBUlJBWVsn
YXBwbGUnLCdiYW5hbmEnLCdjaGVycnknXTo6dGV4dFtdIEBAICdkdXJpYW4gfCBncmFwZSc6OmFu
eXF1ZXJ5OworCistLSBlbXB0eSBhcnJheQorU0VMRUNUIEFSUkFZW106OmludDhbXSBAQCAnMSc6
OmFueXF1ZXJ5OworU0VMRUNUIEFSUkFZW106OmludDhbXSBAQCAnITEnOjphbnlxdWVyeTsKKwor
LS0gcGFyc2UgZXJyb3JzCitTRUxFQ1QgJyc6OmFueXF1ZXJ5OworU0VMRUNUICcxICYnOjphbnlx
dWVyeTsKK1NFTEVDVCAnMSAmICgyJzo6YW55cXVlcnk7CitTRUxFQ1QgJzEgKSAyJzo6YW55cXVl
cnk7CisKKy0tIHJ1bnRpbWUgZXJyb3JzOiB0b2tlbiBjYW5ub3QgYmUgcGFyc2VkIGFzIGVsZW1l
bnQgdHlwZQorU0VMRUNUIEFSUkFZWzEsMl06OmludDhbXSBAQCAnYWJjJzo6YW55cXVlcnk7CisK
Ky0tCistLSBQaGFzZSAzOiBHaVNUIHNpZ25hdHVyZSBpbmRleAorLS0KKworLS0gYW12YWxpZGF0
ZTogd2VsbC1mb3JtZWQgb3BjbGFzcworU0VMRUNUIGFtbmFtZSwgb3BjbmFtZSBGUk9NIHBnX29w
Y2xhc3Mgb3BjCitMRUZUIEpPSU4gcGdfYW0gYW0gT04gYW0ub2lkID0gb3BjbWV0aG9kCitXSEVS
RSBvcGMub3BjbmFtZSA9ICdhbnlhcnJheV9naXN0X29wcycgQU5EIE5PVCBhbXZhbGlkYXRlKG9w
Yy5vaWQpOworCistLSBpbnQ4IEdpU1Q6IGJ1aWxkIGRldGVybWluaXN0aWMgdGFibGUKK0NSRUFU
RSBUQUJMRSBhbnlhcnJheV9naXN0X2ludDggKGlkIGludCwgYSBpbnQ4W10pOworSU5TRVJUIElO
VE8gYW55YXJyYXlfZ2lzdF9pbnQ4IFZBTFVFUworICAoMSwgQVJSQVlbMSwyLDNdOjppbnQ4W10p
LAorICAoMiwgQVJSQVlbMTAsMjAsMzBdOjppbnQ4W10pLAorICAoMywgQVJSQVlbMTAsMjAsMzBd
OjppbnQ4W10pLAorICAoNCwgQVJSQVlbMSwyLDMsNCw1XTo6aW50OFtdKSwKKyAgKDUsIEFSUkFZ
WzEwMCwyMDBdOjppbnQ4W10pOworCitDUkVBVEUgSU5ERVggYW55YXJyYXlfZ2lzdF9pbnQ4X2lk
eAorICBPTiBhbnlhcnJheV9naXN0X2ludDggVVNJTkcgZ2lzdChhIGFueWFycmF5X2dpc3Rfb3Bz
KTsKKworU0VUIGVuYWJsZV9zZXFzY2FuID0gb2ZmOworCitTRUxFQ1QgaWQgRlJPTSBhbnlhcnJh
eV9naXN0X2ludDggV0hFUkUgYSBAPiBBUlJBWVsxLDJdOjppbnQ4W10gT1JERVIgQlkgaWQ7CitT
RUxFQ1QgaWQgRlJPTSBhbnlhcnJheV9naXN0X2ludDggV0hFUkUgYSAmJiBBUlJBWVsxMCwyMDBd
OjppbnQ4W10gT1JERVIgQlkgaWQ7CitTRUxFQ1QgaWQgRlJPTSBhbnlhcnJheV9naXN0X2ludDgg
V0hFUkUgYSA9IEFSUkFZWzEwLDIwLDMwXTo6aW50OFtdIE9SREVSIEJZIGlkOworU0VMRUNUIGlk
IEZST00gYW55YXJyYXlfZ2lzdF9pbnQ4IFdIRVJFIGEgPEAgQVJSQVlbMSwyLDMsNCw1XTo6aW50
OFtdIE9SREVSIEJZIGlkOworU0VMRUNUIGlkIEZST00gYW55YXJyYXlfZ2lzdF9pbnQ4IFdIRVJF
IGEgQEAgJzEwICYgMjAnOjphbnlxdWVyeSBPUkRFUiBCWSBpZDsKK1NFTEVDVCBpZCBGUk9NIGFu
eWFycmF5X2dpc3RfaW50OCBXSEVSRSBhIEBAICcxIHwgMTAwJzo6YW55cXVlcnkgT1JERVIgQlkg
aWQ7CitTRUxFQ1QgaWQgRlJPTSBhbnlhcnJheV9naXN0X2ludDggV0hFUkUgYSBAQCAnITEgJiAx
MCc6OmFueXF1ZXJ5IE9SREVSIEJZIGlkOworCistLSByZXN1bHQgY29uc2lzdGVuY3k6IEdpU1Qg
bXVzdCBhZ3JlZSB3aXRoIHNlcXNjYW4KK1NFTEVDVCAoCisgIFNFTEVDVCBjb3VudCgqKSBGUk9N
IGFueWFycmF5X2dpc3RfaW50OCBXSEVSRSBhIEA+IEFSUkFZWzEwXTo6aW50OFtdCispID0gKAor
ICBTRUxFQ1QgY291bnQoKikgRlJPTSAoU0VMRUNUIDEgRlJPTSBhbnlhcnJheV9naXN0X2ludDgg
V0hFUkUgYSBAPiBBUlJBWVsxMF06OmludDhbXSkgcworKSBBUyBnaXN0X21hdGNoZXNfc2Vxc2Nh
bjsKKworUkVTRVQgZW5hYmxlX3NlcXNjYW47CisKKy0tIHRleHQgR2lTVAorQ1JFQVRFIFRBQkxF
IGFueWFycmF5X2dpc3RfdGV4dCAoaWQgaW50LCBhIHRleHRbXSk7CitJTlNFUlQgSU5UTyBhbnlh
cnJheV9naXN0X3RleHQgVkFMVUVTCisgICgxLCBBUlJBWVsnYXBwbGUnLCdiYW5hbmEnXSksCisg
ICgyLCBBUlJBWVsnYmFuYW5hJywnY2hlcnJ5J10pLAorICAoMywgQVJSQVlbJ2FwcGxlJywnY2hl
cnJ5JywnZHVyaWFuJ10pOworCitDUkVBVEUgSU5ERVggYW55YXJyYXlfZ2lzdF90ZXh0X2lkeAor
ICBPTiBhbnlhcnJheV9naXN0X3RleHQgVVNJTkcgZ2lzdChhIGFueWFycmF5X2dpc3Rfb3BzKHNp
Z2xlbj02NCkpOworCitTRVQgZW5hYmxlX3NlcXNjYW4gPSBvZmY7CitTRUxFQ1QgaWQgRlJPTSBh
bnlhcnJheV9naXN0X3RleHQgV0hFUkUgYSBAPiBBUlJBWVsnYXBwbGUnXTo6dGV4dFtdIE9SREVS
IEJZIGlkOworU0VMRUNUIGlkIEZST00gYW55YXJyYXlfZ2lzdF90ZXh0IFdIRVJFIGEgQEAgJ2Fw
cGxlICYgY2hlcnJ5Jzo6YW55cXVlcnkgT1JERVIgQlkgaWQ7CitSRVNFVCBlbmFibGVfc2Vxc2Nh
bjsKKworLS0gc2lnbGVuIGJvdW5kcworQ1JFQVRFIElOREVYIE9OIGFueWFycmF5X2dpc3RfdGV4
dCBVU0lORyBnaXN0KGEgYW55YXJyYXlfZ2lzdF9vcHMoc2lnbGVuPTApKTsKK0NSRUFURSBJTkRF
WCBPTiBhbnlhcnJheV9naXN0X3RleHQgVVNJTkcgZ2lzdChhIGFueWFycmF5X2dpc3Rfb3BzKHNp
Z2xlbj04MTkzKSk7CisKKy0tCistLSBQaGFzZSA0OiBHSU4gaW5kZXggKHBlci10eXBlLCBzdXBw
b3J0cyBzdGFuZGFyZCBvcHMgKyBAQCkKKy0tCisKKy0tIGFtdmFsaWRhdGU6IGFsbCB0aHJlZSBv
cGNsYXNzZXMKK1NFTEVDVCBhbW5hbWUsIG9wY25hbWUgRlJPTSBwZ19vcGNsYXNzIG9wYworTEVG
VCBKT0lOIHBnX2FtIGFtIE9OIGFtLm9pZCA9IG9wY21ldGhvZAorV0hFUkUgb3BjLm9wY25hbWUg
TElLRSAnJWFueXF1ZXJ5X2dpbl9vcHMnIEFORCBOT1QgYW12YWxpZGF0ZShvcGMub2lkKTsKKwor
LS0gaW50OCBHSU4KK0NSRUFURSBUQUJMRSBhbnlhcnJheV9naW5faW50OCAoaWQgaW50LCBhIGlu
dDhbXSk7CitJTlNFUlQgSU5UTyBhbnlhcnJheV9naW5faW50OCBWQUxVRVMKKyAgKDEsIEFSUkFZ
WzEsMiwzXTo6aW50OFtdKSwKKyAgKDIsIEFSUkFZWzEwLDIwLDMwXTo6aW50OFtdKSwKKyAgKDMs
IEFSUkFZWzEwLDIwLDMwXTo6aW50OFtdKSwKKyAgKDQsIEFSUkFZWzEsMiwzLDQsNV06OmludDhb
XSksCisgICg1LCBBUlJBWVsxMDAsMjAwXTo6aW50OFtdKTsKKworQ1JFQVRFIElOREVYIGFueWFy
cmF5X2dpbl9pbnQ4X2lkeAorICBPTiBhbnlhcnJheV9naW5faW50OCBVU0lORyBnaW4oYSBpbnQ4
X2FueXF1ZXJ5X2dpbl9vcHMpOworCitTRVQgZW5hYmxlX3NlcXNjYW4gPSBvZmY7CitTRUxFQ1Qg
aWQgRlJPTSBhbnlhcnJheV9naW5faW50OCBXSEVSRSBhIEA+IEFSUkFZWzEsMl06OmludDhbXSBP
UkRFUiBCWSBpZDsKK1NFTEVDVCBpZCBGUk9NIGFueWFycmF5X2dpbl9pbnQ4IFdIRVJFIGEgJiYg
QVJSQVlbMTAsMjAwXTo6aW50OFtdIE9SREVSIEJZIGlkOworU0VMRUNUIGlkIEZST00gYW55YXJy
YXlfZ2luX2ludDggV0hFUkUgYSBAQCAnMTAgJiAyMCc6OmFueXF1ZXJ5IE9SREVSIEJZIGlkOwor
U0VMRUNUIGlkIEZST00gYW55YXJyYXlfZ2luX2ludDggV0hFUkUgYSBAQCAnKDEgJiAyKSB8IDEw
MCc6OmFueXF1ZXJ5IE9SREVSIEJZIGlkOworU0VMRUNUIGlkIEZST00gYW55YXJyYXlfZ2luX2lu
dDggV0hFUkUgYSBAQCAnITEnOjphbnlxdWVyeSBPUkRFUiBCWSBpZDsKKworLS0gdXVpZCBHSU4K
K0NSRUFURSBUQUJMRSBhbnlhcnJheV9naW5fdXVpZCAoaWQgaW50LCBhIHV1aWRbXSk7CitJTlNF
UlQgSU5UTyBhbnlhcnJheV9naW5fdXVpZCBWQUxVRVMKKyAgKDEsIEFSUkFZWycxMTExMTExMS0x
MTExLTExMTEtMTExMS0xMTExMTExMTExMTEnOjp1dWlkLAorICAgICAgICAgICAgJzIyMjIyMjIy
LTIyMjItMjIyMi0yMjIyLTIyMjIyMjIyMjIyMiddKSwKKyAgKDIsIEFSUkFZWyczMzMzMzMzMy0z
MzMzLTMzMzMtMzMzMy0zMzMzMzMzMzMzMzMnOjp1dWlkXSksCisgICgzLCBBUlJBWVsnMTExMTEx
MTEtMTExMS0xMTExLTExMTEtMTExMTExMTExMTExJzo6dXVpZCwKKyAgICAgICAgICAgICczMzMz
MzMzMy0zMzMzLTMzMzMtMzMzMy0zMzMzMzMzMzMzMzMnXSk7CisKK0NSRUFURSBJTkRFWCBhbnlh
cnJheV9naW5fdXVpZF9pZHgKKyAgT04gYW55YXJyYXlfZ2luX3V1aWQgVVNJTkcgZ2luKGEgdXVp
ZF9hbnlxdWVyeV9naW5fb3BzKTsKKworU0VUIGVuYWJsZV9zZXFzY2FuID0gb2ZmOworU0VMRUNU
IGlkIEZST00gYW55YXJyYXlfZ2luX3V1aWQKKyAgV0hFUkUgYSBAQCAnMTExMTExMTEtMTExMS0x
MTExLTExMTEtMTExMTExMTExMTExICYgMjIyMjIyMjItMjIyMi0yMjIyLTIyMjItMjIyMjIyMjIy
MjIyJzo6YW55cXVlcnkKKyAgT1JERVIgQlkgaWQ7CitTRUxFQ1QgaWQgRlJPTSBhbnlhcnJheV9n
aW5fdXVpZAorICBXSEVSRSBhIEA+IEFSUkFZWycxMTExMTExMS0xMTExLTExMTEtMTExMS0xMTEx
MTExMTExMTEnOjp1dWlkXQorICBPUkRFUiBCWSBpZDsKK1JFU0VUIGVuYWJsZV9zZXFzY2FuOwor
CistLSB0ZXh0IEdJTgorQ1JFQVRFIFRBQkxFIGFueWFycmF5X2dpbl90ZXh0IChpZCBpbnQsIGEg
dGV4dFtdKTsKK0lOU0VSVCBJTlRPIGFueWFycmF5X2dpbl90ZXh0IFZBTFVFUworICAoMSwgQVJS
QVlbJ2FwcGxlJywnYmFuYW5hJ10pLAorICAoMiwgQVJSQVlbJ2JhbmFuYScsJ2NoZXJyeSddKSwK
KyAgKDMsIEFSUkFZWydhcHBsZScsJ2NoZXJyeScsJ2R1cmlhbiddKTsKKworQ1JFQVRFIElOREVY
IGFueWFycmF5X2dpbl90ZXh0X2lkeAorICBPTiBhbnlhcnJheV9naW5fdGV4dCBVU0lORyBnaW4o
YSB0ZXh0X2FueXF1ZXJ5X2dpbl9vcHMpOworCitTRVQgZW5hYmxlX3NlcXNjYW4gPSBvZmY7CitT
RUxFQ1QgaWQgRlJPTSBhbnlhcnJheV9naW5fdGV4dCBXSEVSRSBhIEBAICdhcHBsZSAmIGNoZXJy
eSc6OmFueXF1ZXJ5IE9SREVSIEJZIGlkOworU0VMRUNUIGlkIEZST00gYW55YXJyYXlfZ2luX3Rl
eHQgV0hFUkUgYSBAQCAnImR1cmlhbiInOjphbnlxdWVyeSBPUkRFUiBCWSBpZDsKK1NFTEVDVCBp
ZCBGUk9NIGFueWFycmF5X2dpbl90ZXh0IFdIRVJFIGEgQEAgJ2FwcGxlIHwgZ3JhcGUnOjphbnlx
dWVyeSBPUkRFUiBCWSBpZDsKK1NFTEVDVCBpZCBGUk9NIGFueWFycmF5X2dpbl90ZXh0IFdIRVJF
IGEgQEAgJyFiYW5hbmEnOjphbnlxdWVyeSBPUkRFUiBCWSBpZDsKK1JFU0VUIGVuYWJsZV9zZXFz
Y2FuOworCistLQorLS0gUGhhc2UgNTogY3Jvc3MtQU0gY29uc2lzdGVuY3kgYW5kIGVkZ2UgY2Fz
ZXMKKy0tCistLSBCdWlsZCBhIGxhcmdlciBkZXRlcm1pbmlzdGljIGludDggdGFibGUgYW5kIGlu
ZGV4IGl0IHdpdGggYm90aCBHaVNUIGFuZAorLS0gR0lOLiAgVGhlbiBydW4gZWFjaCBjYW5kaWRh
dGUgcXVlcnkgdW5kZXIgc2Vxc2NhbiwgR2lTVCBhbmQgR0lOIGFuZCBjaGVjaworLS0gdGhhdCBh
bGwgdGhyZWUgcGxhbnMgcmV0dXJuIHRoZSBzYW1lIHJvdyBzZXQuCistLQorCitDUkVBVEUgVEFC
TEUgYW55YXJyYXlfeGNoZWNrIChpZCBpbnQsIGEgaW50OFtdKTsKKworSU5TRVJUIElOVE8gYW55
YXJyYXlfeGNoZWNrCitTRUxFQ1QgZywKKyAgICAgICBBUlJBWVsoZyAlIDcpOjppbnQ4LCAoKGcg
KiAzKSAlIDExKTo6aW50OCwgKChnICsgMSkgJSA1KTo6aW50OF0KK0ZST00gZ2VuZXJhdGVfc2Vy
aWVzKDEsIDIwMCkgZzsKKy0tIGEgZmV3IGhhbmQtcGlja2VkIHJvd3MgdG8gZXhlcmNpc2UgY29t
bW9uIHZhbHVlcworSU5TRVJUIElOVE8gYW55YXJyYXlfeGNoZWNrIFZBTFVFUworICAoMTAwMSwg
QVJSQVlbMSwyLDMsNCw1XTo6aW50OFtdKSwKKyAgKDEwMDIsIEFSUkFZWzEsMiwzLDQsNV06Omlu
dDhbXSksCisgICgxMDAzLCBBUlJBWVsxMDAsMjAwLDMwMF06OmludDhbXSksCisgICgxMDA0LCBB
UlJBWVtdOjppbnQ4W10pLAorICAoMTAwNSwgTlVMTCk7CisKK0NSRUFURSBJTkRFWCBhbnlhcnJh
eV94Y2hlY2tfZ2lzdCBPTiBhbnlhcnJheV94Y2hlY2sKKyAgVVNJTkcgZ2lzdChhIGFueWFycmF5
X2dpc3Rfb3BzKTsKK0NSRUFURSBJTkRFWCBhbnlhcnJheV94Y2hlY2tfZ2luIE9OIGFueWFycmF5
X3hjaGVjaworICBVU0lORyBnaW4oYSBpbnQ4X2FueXF1ZXJ5X2dpbl9vcHMpOworCistLSBSdW4g
ZWFjaCBwcmVkaWNhdGUgdGhyZWUgdGltZXM6IHB1cmUgc2Vxc2NhbiwgR2lTVC1vbmx5LCBHSU4t
b25seS4KKy0tIEFsbCB0aHJlZSByZXN1bHQgc2V0cyBtdXN0IG1hdGNoLgorQ1JFQVRFIEZVTkNU
SU9OIGFueWFycmF5X3hjaGVja19tYXRjaChwcmVkIHRleHQpCitSRVRVUk5TIFRBQkxFKGdpc3Rf
b2sgYm9vbCwgZ2luX29rIGJvb2wpCitMQU5HVUFHRSBwbHBnc3FsIEFTICQkCitERUNMQVJFCisg
IHNlcSBpbnRbXTsgZ3N0IGludFtdOyBnaW4gaW50W107CitCRUdJTgorICBTRVQgTE9DQUwgZW5h
YmxlX3NlcXNjYW4gPSBvbjsKKyAgU0VUIExPQ0FMIGVuYWJsZV9pbmRleHNjYW4gPSBvZmY7Cisg
IFNFVCBMT0NBTCBlbmFibGVfYml0bWFwc2NhbiA9IG9mZjsKKyAgRVhFQ1VURSAnU0VMRUNUIGFy
cmF5X2FnZyhpZCBPUkRFUiBCWSBpZCkgRlJPTSBhbnlhcnJheV94Y2hlY2sgV0hFUkUgJworICAg
ICAgICAgIHx8IHByZWQgSU5UTyBzZXE7CisKKyAgLS0gRm9yY2UgR2lTVCBieSBoaWRpbmcgdGhl
IEdJTiBpbmRleC4KKyAgQUxURVIgSU5ERVggYW55YXJyYXlfeGNoZWNrX2dpbiBTRVQgKGZhc3R1
cGRhdGUgPSBvZmYpOworICBTRVQgTE9DQUwgZW5hYmxlX3NlcXNjYW4gPSBvZmY7CisgIFNFVCBM
T0NBTCBlbmFibGVfaW5kZXhzY2FuID0gb247CisgIFNFVCBMT0NBTCBlbmFibGVfYml0bWFwc2Nh
biA9IG9uOworICBEUk9QIElOREVYIGFueWFycmF5X3hjaGVja19naW47CisgIEVYRUNVVEUgJ1NF
TEVDVCBhcnJheV9hZ2coaWQgT1JERVIgQlkgaWQpIEZST00gYW55YXJyYXlfeGNoZWNrIFdIRVJF
ICcKKyAgICAgICAgICB8fCBwcmVkIElOVE8gZ3N0OworICBDUkVBVEUgSU5ERVggYW55YXJyYXlf
eGNoZWNrX2dpbiBPTiBhbnlhcnJheV94Y2hlY2sKKyAgICBVU0lORyBnaW4oYSBpbnQ4X2FueXF1
ZXJ5X2dpbl9vcHMpOworCisgIC0tIEZvcmNlIEdJTiBieSBoaWRpbmcgR2lTVC4KKyAgRFJPUCBJ
TkRFWCBhbnlhcnJheV94Y2hlY2tfZ2lzdDsKKyAgRVhFQ1VURSAnU0VMRUNUIGFycmF5X2FnZyhp
ZCBPUkRFUiBCWSBpZCkgRlJPTSBhbnlhcnJheV94Y2hlY2sgV0hFUkUgJworICAgICAgICAgIHx8
IHByZWQgSU5UTyBnaW47CisgIENSRUFURSBJTkRFWCBhbnlhcnJheV94Y2hlY2tfZ2lzdCBPTiBh
bnlhcnJheV94Y2hlY2sKKyAgICBVU0lORyBnaXN0KGEgYW55YXJyYXlfZ2lzdF9vcHMpOworCisg
IGdpc3Rfb2sgOj0gc2VxIElTIE5PVCBESVNUSU5DVCBGUk9NIGdzdDsKKyAgZ2luX29rICA6PSBz
ZXEgSVMgTk9UIERJU1RJTkNUIEZST00gZ2luOworICBSRVRVUk4gTkVYVDsKK0VORCAkJDsKKwor
U0VMRUNUIHByZWQsIGdpc3Rfb2ssIGdpbl9vayBGUk9NIChWQUxVRVMKKyAgKCdhIEA+IEFSUkFZ
WzEsMl06OmludDhbXScpLAorICAoJ2EgQD4gQVJSQVlbMTAwLDIwMF06OmludDhbXScpLAorICAo
J2EgJiYgQVJSQVlbNSw5OV06OmludDhbXScpLAorICAoJ2EgPSBBUlJBWVsxLDIsMyw0LDVdOjpp
bnQ4W10nKSwKKyAgKCdhIEBAICcnMSAmIDInJzo6YW55cXVlcnknKSwKKyAgKCdhIEBAICcnMTAw
IHwgOTk5Jyc6OmFueXF1ZXJ5JyksCisgICgnYSBAQCAnJyExICYgMicnOjphbnlxdWVyeScpCisp
IHYocHJlZCksIExBVEVSQUwgYW55YXJyYXlfeGNoZWNrX21hdGNoKHByZWQpOworCistLSBFZGdl
IGNhc2VzOiBlbXB0eSAvIE5VTEwgYXJyYXlzIHZpYSBpbmRleAorU0VUIGVuYWJsZV9zZXFzY2Fu
ID0gb2ZmOworU0VMRUNUIGlkIEZST00gYW55YXJyYXlfeGNoZWNrIFdIRVJFIGEgQD4gQVJSQVlb
XTo6aW50OFtdIEFORCBpZCA9IDEwMDQ7CitTRUxFQ1QgaWQgRlJPTSBhbnlhcnJheV94Y2hlY2sg
V0hFUkUgYSA8QCBBUlJBWVsxLDIsM106OmludDhbXSBBTkQgaWQgPCAxMDAgT1JERVIgQlkgaWQg
TElNSVQgMzsKK1NFTEVDVCBjb3VudCgqKSBGUk9NIGFueWFycmF5X3hjaGVjayBXSEVSRSBhIElT
IE5VTEw7CitSRVNFVCBlbmFibGVfc2Vxc2NhbjsKKworLS0gREVMRVRFIC8gVkFDVVVNIC8gcmUt
cXVlcnkgdGhyb3VnaCBpbmRleAorREVMRVRFIEZST00gYW55YXJyYXlfeGNoZWNrIFdIRVJFIGlk
IEJFVFdFRU4gMSBBTkQgNTA7CitWQUNVVU0gYW55YXJyYXlfeGNoZWNrOworU0VUIGVuYWJsZV9z
ZXFzY2FuID0gb2ZmOworU0VMRUNUIGNvdW50KCopIEZST00gYW55YXJyYXlfeGNoZWNrIFdIRVJF
IGEgQEAgJzEgfCAyJzo6YW55cXVlcnk7CitSRVNFVCBlbmFibGVfc2Vxc2NhbjsKKworRFJPUCBG
VU5DVElPTiBhbnlhcnJheV94Y2hlY2tfbWF0Y2godGV4dCk7CmRpZmYgLS1naXQgYS9jb250cmli
L21lc29uLmJ1aWxkIGIvY29udHJpYi9tZXNvbi5idWlsZAppbmRleCBlYmI3ZjgzZDhjNS4uZTE1
OGYxOGZhN2UgMTAwNjQ0Ci0tLSBhL2NvbnRyaWIvbWVzb24uYnVpbGQKKysrIGIvY29udHJpYi9t
ZXNvbi5idWlsZApAQCAtMTMsNiArMTMsNyBAQCBjb250cmliX2RvY19hcmdzID0gewogfQogCiBz
dWJkaXIoJ2FtY2hlY2snKQorc3ViZGlyKCdhbnlhcnJheScpCiBzdWJkaXIoJ2F1dGhfZGVsYXkn
KQogc3ViZGlyKCdhdXRvX2V4cGxhaW4nKQogc3ViZGlyKCdiYXNpY19hcmNoaXZlJykKZGlmZiAt
LWdpdCBhL2RvYy9zcmMvc2dtbC9hbnlhcnJheS5zZ21sIGIvZG9jL3NyYy9zZ21sL2FueWFycmF5
LnNnbWwKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAuLjRmMzc2ZTA4Njhj
Ci0tLSAvZGV2L251bGwKKysrIGIvZG9jL3NyYy9zZ21sL2FueWFycmF5LnNnbWwKQEAgLTAsMCAr
MSw0ODIgQEAKKzwhLS0gZG9jL3NyYy9zZ21sL2FueWFycmF5LnNnbWwgLS0+CisKKzxzZWN0MSBp
ZD0iYW55YXJyYXkiIHhyZWZsYWJlbD0iYW55YXJyYXkiPgorIDx0aXRsZT5hbnlhcnJheSAmbWRh
c2g7IG9wZXJhdGlvbnMgYW5kIGluZGV4ZXMgZm9yIGFycmF5cyBvZiBhbnkgdHlwZTwvdGl0bGU+
CisKKyA8aW5kZXh0ZXJtIHpvbmU9ImFueWFycmF5Ij4KKyAgPHByaW1hcnk+YW55YXJyYXk8L3By
aW1hcnk+CisgPC9pbmRleHRlcm0+CisKKyA8cGFyYT4KKyAgVGhlIDxmaWxlbmFtZT5hbnlhcnJh
eTwvZmlsZW5hbWU+IG1vZHVsZSBnZW5lcmFsaXplcworICA8eHJlZiBsaW5rZW5kPSJpbnRhcnJh
eSIvPi1zdHlsZSBvcGVyYXRpb25zIHRvIGFycmF5cyBvZiBhbnkgZWxlbWVudCB0eXBlCisgIHRo
YXQgcHJvdmlkZXMgYSBkZWZhdWx0IEItdHJlZSBvcGNsYXNzLiAgSXQgYWRkcyBzZXQtc3R5bGUg
aGVscGVycywgYQorICB0ZXh0dWFsIGJvb2xlYW4gcXVlcnkgdHlwZSAoPHR5cGU+YW55cXVlcnk8
L3R5cGU+KSwgYW5kIGluZGV4IHN1cHBvcnQgdGhhdAorICB3b3JrcyBmb3IgYXJiaXRyYXJ5IGVs
ZW1lbnQgdHlwZXMuCisgPC9wYXJhPgorCisgPHBhcmE+CisgIEFsbCBvcGVyYXRpb25zIHJlamVj
dCBhcnJheXMgdGhhdCBjb250YWluIDxsaXRlcmFsPk5VTEw8L2xpdGVyYWw+IGVsZW1lbnRzLAor
ICBhbmQgdGhleSBhcmUgZGVmaW5lZCBvbmx5IGZvciBvbmUtZGltZW5zaW9uYWwgYXJyYXlzLgor
IDwvcGFyYT4KKworIDxwYXJhPgorICBUaGlzIG1vZHVsZSBpcyBub3QgbWFya2VkIGFzIDxxdW90
ZT50cnVzdGVkPC9xdW90ZT46IGluc3RhbGxpbmcgaXQKKyAgcmVxdWlyZXMgZGF0YWJhc2UtbGV2
ZWwgcHJpdmlsZWdlcywgYmVjYXVzZSB0aGUgaW5kZXggb3BlcmF0b3IgY2xhc3NlcworICBpdCBk
ZWZpbmVzIHJlZmVyIHRvIGludGVybmFsIHN0b3JhZ2UgdHlwZXMuCisgPC9wYXJhPgorCisgPHNl
Y3QyIGlkPSJhbnlhcnJheS1mdW5jcy1vcHMiPgorICA8dGl0bGU+PGZpbGVuYW1lPmFueWFycmF5
PC9maWxlbmFtZT4gRnVuY3Rpb25zIGFuZCBPcGVyYXRvcnM8L3RpdGxlPgorCisgIDxwYXJhPgor
ICAgVGhlIGZ1bmN0aW9ucyBwcm92aWRlZCBieSA8ZmlsZW5hbWU+YW55YXJyYXk8L2ZpbGVuYW1l
PiBhcmUgbGlzdGVkIGluCisgICA8eHJlZiBsaW5rZW5kPSJhbnlhcnJheS1mdW5jLXRhYmxlIi8+
LCB0aGUgb3BlcmF0b3JzIGluCisgICA8eHJlZiBsaW5rZW5kPSJhbnlhcnJheS1vcC10YWJsZSIv
Pi4KKyAgPC9wYXJhPgorCisgIDx0YWJsZSBpZD0iYW55YXJyYXktZnVuYy10YWJsZSI+CisgICA8
dGl0bGU+PGZpbGVuYW1lPmFueWFycmF5PC9maWxlbmFtZT4gRnVuY3Rpb25zPC90aXRsZT4KKyAg
ICA8dGdyb3VwIGNvbHM9IjEiPgorICAgICA8dGhlYWQ+CisgICAgICA8cm93PgorICAgICAgIDxl
bnRyeSByb2xlPSJmdW5jX3RhYmxlX2VudHJ5Ij48cGFyYSByb2xlPSJmdW5jX3NpZ25hdHVyZSI+
CisgICAgICAgIEZ1bmN0aW9uCisgICAgICAgPC9wYXJhPgorICAgICAgIDxwYXJhPgorICAgICAg
ICBEZXNjcmlwdGlvbgorICAgICAgIDwvcGFyYT4KKyAgICAgICA8cGFyYT4KKyAgICAgICAgRXhh
bXBsZShzKQorICAgICAgIDwvcGFyYT48L2VudHJ5PgorICAgICAgPC9yb3c+CisgICAgIDwvdGhl
YWQ+CisKKyAgICAgPHRib2R5PgorICAgICAgPHJvdz4KKyAgICAgICA8ZW50cnkgcm9sZT0iZnVu
Y190YWJsZV9lbnRyeSI+PHBhcmEgcm9sZT0iZnVuY19zaWduYXR1cmUiPgorICAgICAgICA8ZnVu
Y3Rpb24+YW55YXJyYXlfc29ydDwvZnVuY3Rpb24+ICggPHR5cGU+YW55YXJyYXk8L3R5cGU+IFss
IDx0eXBlPnRleHQ8L3R5cGU+IF0gKQorICAgICAgICA8cmV0dXJudmFsdWU+YW55YXJyYXk8L3Jl
dHVybnZhbHVlPgorICAgICAgIDwvcGFyYT4KKyAgICAgICA8cGFyYT4KKyAgICAgICAgU29ydHMg
YW4gYXJyYXkuICBUaGUgb3B0aW9uYWwgc2Vjb25kIGFyZ3VtZW50IGlzCisgICAgICAgIDxsaXRl
cmFsPmFzYzwvbGl0ZXJhbD4gKGRlZmF1bHQpIG9yIDxsaXRlcmFsPmRlc2M8L2xpdGVyYWw+Lgor
ICAgICAgIDwvcGFyYT4KKyAgICAgICA8cGFyYT4KKyAgICAgICAgPGxpdGVyYWw+YW55YXJyYXlf
c29ydCgnezMsMSwyfSc6OmludDhbXSk8L2xpdGVyYWw+CisgICAgICAgIDxyZXR1cm52YWx1ZT57
MSwyLDN9PC9yZXR1cm52YWx1ZT4KKyAgICAgICA8L3BhcmE+PC9lbnRyeT4KKyAgICAgIDwvcm93
PgorCisgICAgICA8cm93PgorICAgICAgIDxlbnRyeSByb2xlPSJmdW5jX3RhYmxlX2VudHJ5Ij48
cGFyYSByb2xlPSJmdW5jX3NpZ25hdHVyZSI+CisgICAgICAgIDxmdW5jdGlvbj5hbnlhcnJheV91
bmlxPC9mdW5jdGlvbj4gKCA8dHlwZT5hbnlhcnJheTwvdHlwZT4gKQorICAgICAgICA8cmV0dXJu
dmFsdWU+YW55YXJyYXk8L3JldHVybnZhbHVlPgorICAgICAgIDwvcGFyYT4KKyAgICAgICA8cGFy
YT4KKyAgICAgICAgUmVtb3ZlcyBkdXBsaWNhdGVzIGZyb20gdGhlIGFycmF5LCByZXR1cm5pbmcg
dGhlIHNvcnRlZCB1bmlxdWUKKyAgICAgICAgZWxlbWVudHMuCisgICAgICAgPC9wYXJhPgorICAg
ICAgIDxwYXJhPgorICAgICAgICA8bGl0ZXJhbD5hbnlhcnJheV91bmlxKCd7MSwxLDIsMywzfSc6
OmludDhbXSk8L2xpdGVyYWw+CisgICAgICAgIDxyZXR1cm52YWx1ZT57MSwyLDN9PC9yZXR1cm52
YWx1ZT4KKyAgICAgICA8L3BhcmE+PC9lbnRyeT4KKyAgICAgIDwvcm93PgorCisgICAgICA8cm93
PgorICAgICAgIDxlbnRyeSByb2xlPSJmdW5jX3RhYmxlX2VudHJ5Ij48cGFyYSByb2xlPSJmdW5j
X3NpZ25hdHVyZSI+CisgICAgICAgIDxmdW5jdGlvbj5hbnlhcnJheV9pZHg8L2Z1bmN0aW9uPiAo
IDx0eXBlPmFueWFycmF5PC90eXBlPiwgPHR5cGU+YW55ZWxlbWVudDwvdHlwZT4gKQorICAgICAg
ICA8cmV0dXJudmFsdWU+aW50ZWdlcjwvcmV0dXJudmFsdWU+CisgICAgICAgPC9wYXJhPgorICAg
ICAgIDxwYXJhPgorICAgICAgICBSZXR1cm5zIHRoZSAxLWJhc2VkIGluZGV4IG9mIHRoZSBmaXJz
dCBvY2N1cnJlbmNlIG9mIHRoZSBlbGVtZW50LAorICAgICAgICBvciAwIGlmIG5vdCBmb3VuZC4K
KyAgICAgICA8L3BhcmE+CisgICAgICAgPHBhcmE+CisgICAgICAgIDxsaXRlcmFsPmFueWFycmF5
X2lkeChBUlJBWVsnYScsJ2InLCdjJ10sICdiJyk8L2xpdGVyYWw+CisgICAgICAgIDxyZXR1cm52
YWx1ZT4yPC9yZXR1cm52YWx1ZT4KKyAgICAgICA8L3BhcmE+PC9lbnRyeT4KKyAgICAgIDwvcm93
PgorCisgICAgICA8cm93PgorICAgICAgIDxlbnRyeSByb2xlPSJmdW5jX3RhYmxlX2VudHJ5Ij48
cGFyYSByb2xlPSJmdW5jX3NpZ25hdHVyZSI+CisgICAgICAgIDxmdW5jdGlvbj5hbnlhcnJheV9z
dWJhcnJheTwvZnVuY3Rpb24+ICggPHR5cGU+YW55YXJyYXk8L3R5cGU+LCA8cGFyYW1ldGVyPnN0
YXJ0PC9wYXJhbWV0ZXI+IDx0eXBlPmludGVnZXI8L3R5cGU+IFssIDxwYXJhbWV0ZXI+bGVuZ3Ro
PC9wYXJhbWV0ZXI+IDx0eXBlPmludGVnZXI8L3R5cGU+IF0gKQorICAgICAgICA8cmV0dXJudmFs
dWU+YW55YXJyYXk8L3JldHVybnZhbHVlPgorICAgICAgIDwvcGFyYT4KKyAgICAgICA8cGFyYT4K
KyAgICAgICAgUmV0dXJucyBhIGNvbnRpZ3VvdXMgc2xpY2Ugc3RhcnRpbmcgYXQgPHBhcmFtZXRl
cj5zdGFydDwvcGFyYW1ldGVyPgorICAgICAgICAoMS1iYXNlZCkuICBJZiA8cGFyYW1ldGVyPmxl
bmd0aDwvcGFyYW1ldGVyPiBpcyBvbWl0dGVkIHRoZSBzbGljZQorICAgICAgICBleHRlbmRzIHRv
IHRoZSBlbmQgb2YgdGhlIGFycmF5LiAgT3V0LW9mLXJhbmdlIHBvc2l0aW9ucyBvcgorICAgICAg
ICBub24tcG9zaXRpdmUgbGVuZ3RocyBwcm9kdWNlIGFuIGVtcHR5IGFycmF5LgorICAgICAgIDwv
cGFyYT4KKyAgICAgICA8cGFyYT4KKyAgICAgICAgPGxpdGVyYWw+YW55YXJyYXlfc3ViYXJyYXko
J3sxLDIsMyw0LDV9Jzo6aW50OFtdLCAyLCAyKTwvbGl0ZXJhbD4KKyAgICAgICAgPHJldHVybnZh
bHVlPnsyLDN9PC9yZXR1cm52YWx1ZT4KKyAgICAgICA8L3BhcmE+PC9lbnRyeT4KKyAgICAgIDwv
cm93PgorCisgICAgICA8cm93PgorICAgICAgIDxlbnRyeSByb2xlPSJmdW5jX3RhYmxlX2VudHJ5
Ij48cGFyYSByb2xlPSJmdW5jX3NpZ25hdHVyZSI+CisgICAgICAgIDxmdW5jdGlvbj5hbnlhcnJh
eV9pY291bnQ8L2Z1bmN0aW9uPiAoIDx0eXBlPmFueWFycmF5PC90eXBlPiApCisgICAgICAgIDxy
ZXR1cm52YWx1ZT5pbnRlZ2VyPC9yZXR1cm52YWx1ZT4KKyAgICAgICA8L3BhcmE+CisgICAgICAg
PHBhcmE+CisgICAgICAgIFJldHVybnMgdGhlIG51bWJlciBvZiBlbGVtZW50cyBpbiB0aGUgYXJy
YXkgKGV4cG9zZWQgdW5kZXIgdGhlCisgICAgICAgIDxsaXRlcmFsPiM8L2xpdGVyYWw+IG9wZXJh
dG9yKS4KKyAgICAgICA8L3BhcmE+CisgICAgICAgPHBhcmE+CisgICAgICAgIDxsaXRlcmFsPmFu
eWFycmF5X2ljb3VudCgnezEwLDIwLDMwfSc6OmludDhbXSk8L2xpdGVyYWw+CisgICAgICAgIDxy
ZXR1cm52YWx1ZT4zPC9yZXR1cm52YWx1ZT4KKyAgICAgICA8L3BhcmE+PC9lbnRyeT4KKyAgICAg
IDwvcm93PgorCisgICAgICA8cm93PgorICAgICAgIDxlbnRyeSByb2xlPSJmdW5jX3RhYmxlX2Vu
dHJ5Ij48cGFyYSByb2xlPSJmdW5jX3NpZ25hdHVyZSI+CisgICAgICAgIDxmdW5jdGlvbj5hbnlh
cnJheV9pbnRlcnNlY3Q8L2Z1bmN0aW9uPiAoIDx0eXBlPmFueWFycmF5PC90eXBlPiwgPHR5cGU+
YW55YXJyYXk8L3R5cGU+ICkKKyAgICAgICAgPHJldHVybnZhbHVlPmFueWFycmF5PC9yZXR1cm52
YWx1ZT4KKyAgICAgICA8L3BhcmE+CisgICAgICAgPHBhcmE+CisgICAgICAgIFJldHVybnMgdGhl
IHNvcnRlZCwgZGVkdXBsaWNhdGVkIHZhbHVlcyBwcmVzZW50IGluIGJvdGggaW5wdXRzLgorICAg
ICAgIDwvcGFyYT4KKyAgICAgICA8cGFyYT4KKyAgICAgICAgPGxpdGVyYWw+YW55YXJyYXlfaW50
ZXJzZWN0KCd7MSwyLDN9Jzo6aW50OFtdLCAnezIsMyw0fScpPC9saXRlcmFsPgorICAgICAgICA8
cmV0dXJudmFsdWU+ezIsM308L3JldHVybnZhbHVlPgorICAgICAgIDwvcGFyYT48L2VudHJ5Pgor
ICAgICAgPC9yb3c+CisKKyAgICAgIDxyb3c+CisgICAgICAgPGVudHJ5IHJvbGU9ImZ1bmNfdGFi
bGVfZW50cnkiPjxwYXJhIHJvbGU9ImZ1bmNfc2lnbmF0dXJlIj4KKyAgICAgICAgPGZ1bmN0aW9u
PmFueWFycmF5X3VuaW9uPC9mdW5jdGlvbj4gKCA8dHlwZT5hbnlhcnJheTwvdHlwZT4sIDx0eXBl
PmFueWFycmF5PC90eXBlPiApCisgICAgICAgIDxyZXR1cm52YWx1ZT5hbnlhcnJheTwvcmV0dXJu
dmFsdWU+CisgICAgICAgPC9wYXJhPgorICAgICAgIDxwYXJhPgorICAgICAgICBSZXR1cm5zIHRo
ZSBzb3J0ZWQsIGRlZHVwbGljYXRlZCB1bmlvbiBvZiBib3RoIGlucHV0cy4KKyAgICAgICA8L3Bh
cmE+CisgICAgICAgPHBhcmE+CisgICAgICAgIDxsaXRlcmFsPmFueWFycmF5X3VuaW9uKCd7MSwy
fSc6OmludDhbXSwgJ3syLDN9Jyk8L2xpdGVyYWw+CisgICAgICAgIDxyZXR1cm52YWx1ZT57MSwy
LDN9PC9yZXR1cm52YWx1ZT4KKyAgICAgICA8L3BhcmE+PC9lbnRyeT4KKyAgICAgIDwvcm93Pgor
CisgICAgICA8cm93PgorICAgICAgIDxlbnRyeSByb2xlPSJmdW5jX3RhYmxlX2VudHJ5Ij48cGFy
YSByb2xlPSJmdW5jX3NpZ25hdHVyZSI+CisgICAgICAgIDxmdW5jdGlvbj5hbnlhcnJheV91bmlv
bl9lbGVtPC9mdW5jdGlvbj4gKCA8dHlwZT5hbnlhcnJheTwvdHlwZT4sIDx0eXBlPmFueWVsZW1l
bnQ8L3R5cGU+ICkKKyAgICAgICAgPHJldHVybnZhbHVlPmFueWFycmF5PC9yZXR1cm52YWx1ZT4K
KyAgICAgICA8L3BhcmE+CisgICAgICAgPHBhcmE+CisgICAgICAgIEFkZHMgYW4gZWxlbWVudCB0
byB0aGUgYXJyYXkgaWYgbm90IGFscmVhZHkgcHJlc2VudDsgcmVzdWx0IGlzCisgICAgICAgIHNv
cnRlZCBhbmQgZGVkdXBsaWNhdGVkLgorICAgICAgIDwvcGFyYT4KKyAgICAgICA8cGFyYT4KKyAg
ICAgICAgPGxpdGVyYWw+YW55YXJyYXlfdW5pb25fZWxlbSgnezEsMiwzfSc6OmludDhbXSwgNDo6
aW50OCk8L2xpdGVyYWw+CisgICAgICAgIDxyZXR1cm52YWx1ZT57MSwyLDMsNH08L3JldHVybnZh
bHVlPgorICAgICAgIDwvcGFyYT48L2VudHJ5PgorICAgICAgPC9yb3c+CisKKyAgICAgIDxyb3c+
CisgICAgICAgPGVudHJ5IHJvbGU9ImZ1bmNfdGFibGVfZW50cnkiPjxwYXJhIHJvbGU9ImZ1bmNf
c2lnbmF0dXJlIj4KKyAgICAgICAgPGZ1bmN0aW9uPmFueWFycmF5X2RpZmZlcmVuY2U8L2Z1bmN0
aW9uPiAoIDx0eXBlPmFueWFycmF5PC90eXBlPiwgPHR5cGU+YW55YXJyYXk8L3R5cGU+ICkKKyAg
ICAgICAgPHJldHVybnZhbHVlPmFueWFycmF5PC9yZXR1cm52YWx1ZT4KKyAgICAgICA8L3BhcmE+
CisgICAgICAgPHBhcmE+CisgICAgICAgIFJldHVybnMgdGhlIHNvcnRlZCwgZGVkdXBsaWNhdGVk
IHZhbHVlcyBmcm9tIHRoZSBmaXJzdCBhcnJheSB0aGF0CisgICAgICAgIGFyZSBub3QgaW4gdGhl
IHNlY29uZC4KKyAgICAgICA8L3BhcmE+CisgICAgICAgPHBhcmE+CisgICAgICAgIDxsaXRlcmFs
PmFueWFycmF5X2RpZmZlcmVuY2UoJ3sxLDIsMyw0fSc6OmludDhbXSwgJ3syLDR9Jyk8L2xpdGVy
YWw+CisgICAgICAgIDxyZXR1cm52YWx1ZT57MSwzfTwvcmV0dXJudmFsdWU+CisgICAgICAgPC9w
YXJhPjwvZW50cnk+CisgICAgICA8L3Jvdz4KKworICAgICAgPHJvdz4KKyAgICAgICA8ZW50cnkg
cm9sZT0iZnVuY190YWJsZV9lbnRyeSI+PHBhcmEgcm9sZT0iZnVuY19zaWduYXR1cmUiPgorICAg
ICAgICA8ZnVuY3Rpb24+YW55YXJyYXlfZGlmZmVyZW5jZV9lbGVtPC9mdW5jdGlvbj4gKCA8dHlw
ZT5hbnlhcnJheTwvdHlwZT4sIDx0eXBlPmFueWVsZW1lbnQ8L3R5cGU+ICkKKyAgICAgICAgPHJl
dHVybnZhbHVlPmFueWFycmF5PC9yZXR1cm52YWx1ZT4KKyAgICAgICA8L3BhcmE+CisgICAgICAg
PHBhcmE+CisgICAgICAgIFJlbW92ZXMgYWxsIG9jY3VycmVuY2VzIG9mIHRoZSBnaXZlbiBlbGVt
ZW50LCBwcmVzZXJ2aW5nIHRoZQorICAgICAgICByZWxhdGl2ZSBvcmRlciBvZiB0aGUgc3Vydml2
aW5nIGVsZW1lbnRzLgorICAgICAgIDwvcGFyYT4KKyAgICAgICA8cGFyYT4KKyAgICAgICAgPGxp
dGVyYWw+YW55YXJyYXlfZGlmZmVyZW5jZV9lbGVtKCd7MSwyLDIsMywyfSc6OmludDhbXSwgMjo6
aW50OCk8L2xpdGVyYWw+CisgICAgICAgIDxyZXR1cm52YWx1ZT57MSwzfTwvcmV0dXJudmFsdWU+
CisgICAgICAgPC9wYXJhPjwvZW50cnk+CisgICAgICA8L3Jvdz4KKworICAgICAgPHJvdz4KKyAg
ICAgICA8ZW50cnkgcm9sZT0iZnVuY190YWJsZV9lbnRyeSI+PHBhcmEgcm9sZT0iZnVuY19zaWdu
YXR1cmUiPgorICAgICAgICA8ZnVuY3Rpb24+YW55cXVlcnlfcXVlcnl0cmVlPC9mdW5jdGlvbj4g
KCA8dHlwZT5hbnlxdWVyeTwvdHlwZT4gKQorICAgICAgICA8cmV0dXJudmFsdWU+dGV4dDwvcmV0
dXJudmFsdWU+CisgICAgICAgPC9wYXJhPgorICAgICAgIDxwYXJhPgorICAgICAgICBSZXR1cm5z
IHRoZSBxdWVyeSBpbiBwb3N0Zml4IGZvcm07IHVzZWZ1bCBmb3IgZGVidWdnaW5nLgorICAgICAg
IDwvcGFyYT4KKyAgICAgICA8cGFyYT4KKyAgICAgICAgPGxpdGVyYWw+YW55cXVlcnlfcXVlcnl0
cmVlKCcxICZhbXA7IDIgfCAzJzo6YW55cXVlcnkpPC9saXRlcmFsPgorICAgICAgICA8cmV0dXJu
dmFsdWU+MSAyICZhbXA7IDMgfDwvcmV0dXJudmFsdWU+CisgICAgICAgPC9wYXJhPjwvZW50cnk+
CisgICAgICA8L3Jvdz4KKyAgICAgPC90Ym9keT4KKyAgICA8L3Rncm91cD4KKyAgIDwvdGFibGU+
CisKKyAgIDx0YWJsZSBpZD0iYW55YXJyYXktb3AtdGFibGUiPgorICAgIDx0aXRsZT48ZmlsZW5h
bWU+YW55YXJyYXk8L2ZpbGVuYW1lPiBPcGVyYXRvcnM8L3RpdGxlPgorICAgICA8dGdyb3VwIGNv
bHM9IjEiPgorICAgICAgPHRoZWFkPgorICAgICAgIDxyb3c+CisgICAgICAgIDxlbnRyeSByb2xl
PSJmdW5jX3RhYmxlX2VudHJ5Ij48cGFyYSByb2xlPSJmdW5jX3NpZ25hdHVyZSI+CisgICAgICAg
ICBPcGVyYXRvcgorICAgICAgICA8L3BhcmE+CisgICAgICAgIDxwYXJhPgorICAgICAgICAgRGVz
Y3JpcHRpb24KKyAgICAgICAgPC9wYXJhPjwvZW50cnk+CisgICAgICAgPC9yb3c+CisgICAgICA8
L3RoZWFkPgorCisgICAgICA8dGJvZHk+CisgICAgICAgPHJvdz4KKyAgICAgICAgPGVudHJ5IHJv
bGU9ImZ1bmNfdGFibGVfZW50cnkiPjxwYXJhIHJvbGU9ImZ1bmNfc2lnbmF0dXJlIj4KKyAgICAg
ICAgIDx0eXBlPjwvdHlwZT4gPGxpdGVyYWw+IzwvbGl0ZXJhbD4gPHR5cGU+YW55YXJyYXk8L3R5
cGU+CisgICAgICAgICA8cmV0dXJudmFsdWU+aW50ZWdlcjwvcmV0dXJudmFsdWU+CisgICAgICAg
IDwvcGFyYT4KKyAgICAgICAgPHBhcmE+CisgICAgICAgICBSZXR1cm5zIHRoZSBudW1iZXIgb2Yg
ZWxlbWVudHMgaW4gdGhlIGFycmF5IChwcmVmaXggb3BlcmF0b3IpLgorICAgICAgICA8L3BhcmE+
PC9lbnRyeT4KKyAgICAgICA8L3Jvdz4KKworICAgICAgIDxyb3c+CisgICAgICAgIDxlbnRyeSBy
b2xlPSJmdW5jX3RhYmxlX2VudHJ5Ij48cGFyYSByb2xlPSJmdW5jX3NpZ25hdHVyZSI+CisgICAg
ICAgICA8dHlwZT5hbnlhcnJheTwvdHlwZT4gPGxpdGVyYWw+IzwvbGl0ZXJhbD4gPHR5cGU+YW55
ZWxlbWVudDwvdHlwZT4KKyAgICAgICAgIDxyZXR1cm52YWx1ZT5pbnRlZ2VyPC9yZXR1cm52YWx1
ZT4KKyAgICAgICAgPC9wYXJhPgorICAgICAgICA8cGFyYT4KKyAgICAgICAgIFJldHVybnMgdGhl
IDEtYmFzZWQgaW5kZXggb2YgdGhlIHJpZ2h0IG9wZXJhbmQgaW4gdGhlIGFycmF5LCBvciAwCisg
ICAgICAgICBpZiBub3QgZm91bmQuICBTYW1lIGFzIDxmdW5jdGlvbj5hbnlhcnJheV9pZHg8L2Z1
bmN0aW9uPi4KKyAgICAgICAgPC9wYXJhPjwvZW50cnk+CisgICAgICAgPC9yb3c+CisKKyAgICAg
ICA8cm93PgorICAgICAgICA8ZW50cnkgcm9sZT0iZnVuY190YWJsZV9lbnRyeSI+PHBhcmEgcm9s
ZT0iZnVuY19zaWduYXR1cmUiPgorICAgICAgICAgPHR5cGU+YW55YXJyYXk8L3R5cGU+IDxsaXRl
cmFsPiZhbXA7PC9saXRlcmFsPiA8dHlwZT5hbnlhcnJheTwvdHlwZT4KKyAgICAgICAgIDxyZXR1
cm52YWx1ZT5hbnlhcnJheTwvcmV0dXJudmFsdWU+CisgICAgICAgIDwvcGFyYT4KKyAgICAgICAg
PHBhcmE+CisgICAgICAgICBTZXQgaW50ZXJzZWN0aW9uIG9mIHRoZSBvcGVyYW5kcy4KKyAgICAg
ICAgPC9wYXJhPjwvZW50cnk+CisgICAgICAgPC9yb3c+CisKKyAgICAgICA8cm93PgorICAgICAg
ICA8ZW50cnkgcm9sZT0iZnVuY190YWJsZV9lbnRyeSI+PHBhcmEgcm9sZT0iZnVuY19zaWduYXR1
cmUiPgorICAgICAgICAgPHR5cGU+YW55YXJyYXk8L3R5cGU+IDxsaXRlcmFsPnw8L2xpdGVyYWw+
IDx0eXBlPmFueWFycmF5PC90eXBlPgorICAgICAgICAgPHJldHVybnZhbHVlPmFueWFycmF5PC9y
ZXR1cm52YWx1ZT4KKyAgICAgICAgPC9wYXJhPgorICAgICAgICA8cGFyYT4KKyAgICAgICAgIFNl
dCB1bmlvbiBvZiB0aGUgb3BlcmFuZHMuCisgICAgICAgIDwvcGFyYT48L2VudHJ5PgorICAgICAg
IDwvcm93PgorCisgICAgICAgPHJvdz4KKyAgICAgICAgPGVudHJ5IHJvbGU9ImZ1bmNfdGFibGVf
ZW50cnkiPjxwYXJhIHJvbGU9ImZ1bmNfc2lnbmF0dXJlIj4KKyAgICAgICAgIDx0eXBlPmFueWFy
cmF5PC90eXBlPiA8bGl0ZXJhbD58PC9saXRlcmFsPiA8dHlwZT5hbnllbGVtZW50PC90eXBlPgor
ICAgICAgICAgPHJldHVybnZhbHVlPmFueWFycmF5PC9yZXR1cm52YWx1ZT4KKyAgICAgICAgPC9w
YXJhPgorICAgICAgICA8cGFyYT4KKyAgICAgICAgIEFkZHMgdGhlIHJpZ2h0IG9wZXJhbmQgdG8g
dGhlIGFycmF5IGlmIG5vdCBhbHJlYWR5IHByZXNlbnQuCisgICAgICAgIDwvcGFyYT48L2VudHJ5
PgorICAgICAgIDwvcm93PgorCisgICAgICAgPHJvdz4KKyAgICAgICAgPGVudHJ5IHJvbGU9ImZ1
bmNfdGFibGVfZW50cnkiPjxwYXJhIHJvbGU9ImZ1bmNfc2lnbmF0dXJlIj4KKyAgICAgICAgIDx0
eXBlPmFueWFycmF5PC90eXBlPiA8bGl0ZXJhbD4tPC9saXRlcmFsPiA8dHlwZT5hbnlhcnJheTwv
dHlwZT4KKyAgICAgICAgIDxyZXR1cm52YWx1ZT5hbnlhcnJheTwvcmV0dXJudmFsdWU+CisgICAg
ICAgIDwvcGFyYT4KKyAgICAgICAgPHBhcmE+CisgICAgICAgICBTZXQgZGlmZmVyZW5jZTogZWxl
bWVudHMgb2YgdGhlIGxlZnQgYXJyYXkgbm90IHByZXNlbnQgaW4gdGhlCisgICAgICAgICByaWdo
dC4KKyAgICAgICAgPC9wYXJhPjwvZW50cnk+CisgICAgICAgPC9yb3c+CisKKyAgICAgICA8cm93
PgorICAgICAgICA8ZW50cnkgcm9sZT0iZnVuY190YWJsZV9lbnRyeSI+PHBhcmEgcm9sZT0iZnVu
Y19zaWduYXR1cmUiPgorICAgICAgICAgPHR5cGU+YW55YXJyYXk8L3R5cGU+IDxsaXRlcmFsPi08
L2xpdGVyYWw+IDx0eXBlPmFueWVsZW1lbnQ8L3R5cGU+CisgICAgICAgICA8cmV0dXJudmFsdWU+
YW55YXJyYXk8L3JldHVybnZhbHVlPgorICAgICAgICA8L3BhcmE+CisgICAgICAgIDxwYXJhPgor
ICAgICAgICAgUmVtb3ZlcyBhbGwgb2NjdXJyZW5jZXMgb2YgdGhlIHJpZ2h0IG9wZXJhbmQgZnJv
bSB0aGUgYXJyYXkuCisgICAgICAgIDwvcGFyYT48L2VudHJ5PgorICAgICAgIDwvcm93PgorCisg
ICAgICAgPHJvdz4KKyAgICAgICAgPGVudHJ5IHJvbGU9ImZ1bmNfdGFibGVfZW50cnkiPjxwYXJh
IHJvbGU9ImZ1bmNfc2lnbmF0dXJlIj4KKyAgICAgICAgIDx0eXBlPmFueWFycmF5PC90eXBlPiA8
bGl0ZXJhbD5AQDwvbGl0ZXJhbD4gPHR5cGU+YW55cXVlcnk8L3R5cGU+CisgICAgICAgICA8cmV0
dXJudmFsdWU+Ym9vbGVhbjwvcmV0dXJudmFsdWU+CisgICAgICAgIDwvcGFyYT4KKyAgICAgICAg
PHBhcmE+CisgICAgICAgICBUcnVlIGlmIHRoZSBhcnJheSBzYXRpc2ZpZXMgdGhlIHF1ZXJ5IChz
ZWUgYmVsb3cpLgorICAgICAgICA8L3BhcmE+PC9lbnRyeT4KKyAgICAgICA8L3Jvdz4KKworICAg
ICAgIDxyb3c+CisgICAgICAgIDxlbnRyeSByb2xlPSJmdW5jX3RhYmxlX2VudHJ5Ij48cGFyYSBy
b2xlPSJmdW5jX3NpZ25hdHVyZSI+CisgICAgICAgICA8dHlwZT5hbnlxdWVyeTwvdHlwZT4gPGxp
dGVyYWw+fn48L2xpdGVyYWw+IDx0eXBlPmFueWFycmF5PC90eXBlPgorICAgICAgICAgPHJldHVy
bnZhbHVlPmJvb2xlYW48L3JldHVybnZhbHVlPgorICAgICAgICA8L3BhcmE+CisgICAgICAgIDxw
YXJhPgorICAgICAgICAgQ29tbXV0YXRvciBvZiA8bGl0ZXJhbD5AQDwvbGl0ZXJhbD4uCisgICAg
ICAgIDwvcGFyYT48L2VudHJ5PgorICAgICAgIDwvcm93PgorICAgICAgPC90Ym9keT4KKyAgICAg
PC90Z3JvdXA+CisgICA8L3RhYmxlPgorCisgICA8cGFyYT4KKyAgICBUaGUgb3BlcmF0b3JzIDxs
aXRlcmFsPiZhbXA7JmFtcDs8L2xpdGVyYWw+LCA8bGl0ZXJhbD5AJmd0OzwvbGl0ZXJhbD4sCisg
ICAgPGxpdGVyYWw+Jmx0O0A8L2xpdGVyYWw+IGFuZCA8bGl0ZXJhbD49PC9saXRlcmFsPiBvbiBh
cnJheXMgYXJlCisgICAgPGVtcGhhc2lzPm5vdDwvZW1waGFzaXM+IHJlZGVmaW5lZCBieSB0aGlz
IGV4dGVuc2lvbjsgdGhlIGJ1aWx0LWluCisgICAgUG9zdGdyZVNRTCBvcGVyYXRvcnMgYXJlIHVz
ZWQuCisgICA8L3BhcmE+CisgPC9zZWN0Mj4KKworIDxzZWN0MiBpZD0iYW55YXJyYXktcXVlcnki
PgorICA8dGl0bGU+VGhlIDx0eXBlPmFueXF1ZXJ5PC90eXBlPiBUeXBlPC90aXRsZT4KKworICA8
cGFyYT4KKyAgIDx0eXBlPmFueXF1ZXJ5PC90eXBlPiByZXByZXNlbnRzIGEgYm9vbGVhbiBleHBy
ZXNzaW9uIG92ZXIgYXJyYXkKKyAgIGVsZW1lbnRzLiAgVmFsdWVzIGFyZSB0ZXh0dWFsIHRva2Vu
czsgdGhlIGVsZW1lbnQgdHlwZSB1c2VkIHRvIGludGVycHJldAorICAgdGhlbSBpcyBkZXRlcm1p
bmVkIGJ5IHRoZSBsZWZ0LWhhbmQgc2lkZSBvZiA8bGl0ZXJhbD5AQDwvbGl0ZXJhbD4gYXQKKyAg
IHF1ZXJ5IHRpbWUuICBUb2tlbnMgYXJlIGNvbWJpbmVkIHdpdGggdGhlIG9wZXJhdG9ycworICAg
PGxpdGVyYWw+JmFtcDs8L2xpdGVyYWw+IChBTkQpLCA8bGl0ZXJhbD58PC9saXRlcmFsPiAoT1Ip
IGFuZAorICAgPGxpdGVyYWw+ITwvbGl0ZXJhbD4gKE5PVCkuICBQYXJlbnRoZXNlcyBjb250cm9s
IHByZWNlZGVuY2U7IHdpdGhvdXQKKyAgIHRoZW0gPGxpdGVyYWw+JmFtcDs8L2xpdGVyYWw+IGJp
bmRzIHRpZ2h0ZXIgdGhhbiA8bGl0ZXJhbD58PC9saXRlcmFsPi4KKyAgPC9wYXJhPgorCisgIDxw
YXJhPgorICAgQSB0b2tlbiBjb25zaXN0cyBvZiBhbnkgc2VxdWVuY2Ugb2YgY2hhcmFjdGVycyB0
aGF0IGFyZSBub3Qgd2hpdGVzcGFjZQorICAgb3Igb25lIG9mIDxsaXRlcmFsPiZhbXA7IHwgISAo
ICkgIjwvbGl0ZXJhbD4uICBUbyBpbmNsdWRlIHRob3NlCisgICBjaGFyYWN0ZXJzIG9yIGVtYmVk
ZGVkIHdoaXRlc3BhY2UsIHdyYXAgdGhlIHRva2VuIGluIGRvdWJsZSBxdW90ZXM6CisgICA8bGl0
ZXJhbD4iaGVsbG8gd29ybGQiPC9saXRlcmFsPi4gIEluc2lkZSBxdW90ZXMsIGEgYmFja3NsYXNo
IGVzY2FwZXMKKyAgIHRoZSBuZXh0IGNoYXJhY3Rlci4KKyAgPC9wYXJhPgorCisgIDxwYXJhPgor
ICAgQXQgZXZhbHVhdGlvbiB0aW1lLCBlYWNoIHRva2VuIGlzIHBhcnNlZCBieSB0aGUgaW5wdXQg
ZnVuY3Rpb24gb2YgdGhlCisgICBhcnJheSdzIGVsZW1lbnQgdHlwZS4gIFRoaXMgbWVhbnMKKyAg
IDxsaXRlcmFsPicxICZhbXA7IDInOjphbnlxdWVyeSBAQCBBUlJBWVsxLDIsM106OmJpZ2ludFtd
PC9saXRlcmFsPgorICAgcGFyc2VzIDxxdW90ZT4xPC9xdW90ZT4gYW5kIDxxdW90ZT4yPC9xdW90
ZT4gYXMgPHR5cGU+YmlnaW50PC90eXBlPjsgdGhlCisgICBzYW1lIHF1ZXJ5IGFnYWluc3QgYSA8
dHlwZT50ZXh0W108L3R5cGU+IGNvbHVtbiBjb21wYXJlcyB0aGUgbGl0ZXJhbAorICAgc3RyaW5n
cyA8cXVvdGU+MTwvcXVvdGU+IGFuZCA8cXVvdGU+MjwvcXVvdGU+LiAgQW4gdW5wYXJzZWFibGUg
dG9rZW4KKyAgIHJhaXNlcyBhbiBlcnJvciBhdCA8bGl0ZXJhbD5AQDwvbGl0ZXJhbD4tdGltZSwg
bm90IGF0IHBhcnNlIHRpbWUuCisgIDwvcGFyYT4KKyA8L3NlY3QyPgorCisgPHNlY3QyIGlkPSJh
bnlhcnJheS1pbmRleCI+CisgIDx0aXRsZT5JbmRleCBTdXBwb3J0PC90aXRsZT4KKworICA8cGFy
YT4KKyAgIDxmaWxlbmFtZT5hbnlhcnJheTwvZmlsZW5hbWU+IHByb3ZpZGVzIGEgcG9seW1vcnBo
aWMgR2lTVCBvcGNsYXNzIGFuZAorICAgcGVyLWVsZW1lbnQtdHlwZSBHSU4gb3BjbGFzc2VzLiAg
QWxsIG9mIHRoZW0gc3VwcG9ydCB0aGUgc3RhbmRhcmQgYXJyYXkKKyAgIG9wZXJhdG9ycyAoPGxp
dGVyYWw+JmFtcDsmYW1wOzwvbGl0ZXJhbD4sIDxsaXRlcmFsPkAmZ3Q7PC9saXRlcmFsPiwKKyAg
IDxsaXRlcmFsPiZsdDtAPC9saXRlcmFsPiwgPGxpdGVyYWw+PTwvbGl0ZXJhbD4pIGFzIHdlbGwg
YXMKKyAgIDxsaXRlcmFsPkBAPC9saXRlcmFsPi4KKyAgPC9wYXJhPgorCisgIDxzZWN0MyBpZD0i
YW55YXJyYXktaW5kZXgtZ2lzdCI+CisgICA8dGl0bGU+R2lTVDogPGxpdGVyYWw+YW55YXJyYXlf
Z2lzdF9vcHM8L2xpdGVyYWw+PC90aXRsZT4KKworICAgPHBhcmE+CisgICAgQSBzaW5nbGUgb3Bj
bGFzcyBvbiA8dHlwZT5hbnlhcnJheTwvdHlwZT4gd29ya3MgZm9yIGFueSBlbGVtZW50IHR5cGUK
KyAgICB0aGF0IGhhcyBhIGRlZmF1bHQgaGFzaCBmdW5jdGlvbi4gIEVhY2ggaW5kZXhlZCBhcnJh
eSBpcyBzdW1tYXJpc2VkIGFzCisgICAgYSBmaXhlZC1zaXplIGJpdCB2ZWN0b3IgYnkgaGFzaGlu
ZyBldmVyeSBlbGVtZW50IGludG8gb25lIGJpdDsgaW50ZXJuYWwKKyAgICBub2RlcyBzdG9yZSB0
aGUgdW5pb24gb2YgdGhlaXIgY2hpbGRyZW4uICBBbGwgbWF0Y2hlcyBhcmUgcmVjaGVja2VkCisg
ICAgYmVjYXVzZSBzaWduYXR1cmVzIGFyZSBsb3NzeS4KKyAgIDwvcGFyYT4KKworICAgPHBhcmE+
CisgICAgVGhlIG9wdGlvbmFsIGludGVnZXIgcGFyYW1ldGVyIDxsaXRlcmFsPnNpZ2xlbjwvbGl0
ZXJhbD4gc2V0cyB0aGUKKyAgICBzaWduYXR1cmUgbGVuZ3RoIGluIGJ5dGVzLiAgVGhlIGRlZmF1
bHQgaXMgMjUyIGJ5dGVzICgyMDE2IGJpdHMpOworICAgIHZhbGlkIHZhbHVlcyBhcmUgYmV0d2Vl
biAxIGFuZCB0aGUgaW5kZXgta2V5IHNpemUgbGltaXQuICBMb25nZXIKKyAgICBzaWduYXR1cmVz
IHByb2R1Y2UgbW9yZSBwcmVjaXNlIGluZGV4ZXMgYXQgdGhlIGNvc3Qgb2YgbW9yZSBzdG9yYWdl
LgorICAgPC9wYXJhPgorCisgICA8cHJvZ3JhbWxpc3Rpbmc+CitDUkVBVEUgSU5ERVggbXlfaWR4
IE9OIG15X3RhYmxlIFVTSU5HIGdpc3QgKGNvbCBhbnlhcnJheV9naXN0X29wcyk7CitDUkVBVEUg
SU5ERVggbXlfaWR4IE9OIG15X3RhYmxlIFVTSU5HIGdpc3QgKGNvbCBhbnlhcnJheV9naXN0X29w
cyhzaWdsZW49NjQpKTsKKyAgIDwvcHJvZ3JhbWxpc3Rpbmc+CisgIDwvc2VjdDM+CisKKyAgPHNl
Y3QzIGlkPSJhbnlhcnJheS1pbmRleC1naW4iPgorICAgPHRpdGxlPkdJTjogcGVyLXR5cGUgb3Bj
bGFzc2VzPC90aXRsZT4KKworICAgPHBhcmE+CisgICAgQmVjYXVzZSB0aGUgR0lOIGV4dHJhY3RR
dWVyeSBBUEkgZG9lcyBub3QgZXhwb3NlIHRoZSBpbmRleGVkIGNvbHVtbidzCisgICAgZWxlbWVu
dCB0eXBlIHdoZW4gdGhlIHF1ZXJ5IGlzIGFuIDx0eXBlPmFueXF1ZXJ5PC90eXBlPiwgR0lOIHN1
cHBvcnQKKyAgICBpcyBwcm92aWRlZCBhcyBvbmUgb3BjbGFzcyBwZXIgY29uY3JldGUgZWxlbWVu
dCB0eXBlLiAgQ3VycmVudGx5CisgICAgc3VwcGxpZWQ6CisgICA8L3BhcmE+CisKKyAgIDxpdGVt
aXplZGxpc3Q+CisgICAgPGxpc3RpdGVtPjxwYXJhPgorICAgICA8bGl0ZXJhbD5pbnQ4X2FueXF1
ZXJ5X2dpbl9vcHM8L2xpdGVyYWw+IGZvciA8dHlwZT5iaWdpbnRbXTwvdHlwZT4KKyAgICA8L3Bh
cmE+PC9saXN0aXRlbT4KKyAgICA8bGlzdGl0ZW0+PHBhcmE+CisgICAgIDxsaXRlcmFsPnV1aWRf
YW55cXVlcnlfZ2luX29wczwvbGl0ZXJhbD4gZm9yIDx0eXBlPnV1aWRbXTwvdHlwZT4KKyAgICA8
L3BhcmE+PC9saXN0aXRlbT4KKyAgICA8bGlzdGl0ZW0+PHBhcmE+CisgICAgIDxsaXRlcmFsPnRl
eHRfYW55cXVlcnlfZ2luX29wczwvbGl0ZXJhbD4gZm9yIDx0eXBlPnRleHRbXTwvdHlwZT4KKyAg
ICA8L3BhcmE+PC9saXN0aXRlbT4KKyAgIDwvaXRlbWl6ZWRsaXN0PgorCisgICA8cGFyYT4KKyAg
ICBUaGVzZSBvcGNsYXNzZXMgYXJlIGRyb3AtaW4gcmVwbGFjZW1lbnRzIGZvciB0aGUgYnVpbHQt
aW4KKyAgICA8bGl0ZXJhbD5hcnJheV9vcHM8L2xpdGVyYWw+OyB0aGV5IGFkZGl0aW9uYWxseSBz
dXBwb3J0CisgICAgPGxpdGVyYWw+QEA8L2xpdGVyYWw+LgorICAgPC9wYXJhPgorCisgICA8cHJv
Z3JhbWxpc3Rpbmc+CitDUkVBVEUgSU5ERVggbXlfaWR4IE9OIG15X3RhYmxlIFVTSU5HIGdpbiAo
Y29sIGludDhfYW55cXVlcnlfZ2luX29wcyk7CisgICA8L3Byb2dyYW1saXN0aW5nPgorCisgICA8
cGFyYT4KKyAgICBGb3IgZWxlbWVudCB0eXBlcyBub3QgaW4gdGhlIGxpc3QgYWJvdmUsIHVzZSB0
aGUgYnVpbHQtaW4gR0lOCisgICAgPGxpdGVyYWw+YXJyYXlfb3BzPC9saXRlcmFsPiBmb3Igc2V0
IHF1ZXJpZXMgYW5kIHJlbHkgb24KKyAgICA8bGl0ZXJhbD5hbnlhcnJheV9naXN0X29wczwvbGl0
ZXJhbD4gZm9yIDxsaXRlcmFsPkBAPC9saXRlcmFsPi4KKyAgIDwvcGFyYT4KKyAgPC9zZWN0Mz4K
KyA8L3NlY3QyPgorCisgPHNlY3QyIGlkPSJhbnlhcnJheS1leGFtcGxlIj4KKyAgPHRpdGxlPkV4
YW1wbGU8L3RpdGxlPgorCis8cHJvZ3JhbWxpc3Rpbmc+CitDUkVBVEUgRVhURU5TSU9OIGFueWFy
cmF5OworCitDUkVBVEUgVEFCTEUgbWVzc2FnZSAobWlkIElOVCBQUklNQVJZIEtFWSwgdGFncyBU
RVhUW10pOworCitDUkVBVEUgSU5ERVggbWVzc2FnZV90YWdzX2dpc3QgT04gbWVzc2FnZSBVU0lO
RyBnaXN0ICh0YWdzIGFueWFycmF5X2dpc3Rfb3BzKTsKK0NSRUFURSBJTkRFWCBtZXNzYWdlX3Rh
Z3NfZ2luICBPTiBtZXNzYWdlIFVTSU5HIGdpbiAgKHRhZ3MgdGV4dF9hbnlxdWVyeV9naW5fb3Bz
KTsKKworLS0gTWVzc2FnZXMgdGFnZ2VkIHdpdGggYm90aCAndXJnZW50JyBhbmQgJ2J1Zyc6CitT
RUxFQ1QgbWlkIEZST00gbWVzc2FnZSBXSEVSRSB0YWdzIEAmZ3Q7IEFSUkFZWyd1cmdlbnQnLCdi
dWcnXTsKKworLS0gU2FtZSwgd2l0aCB0aGUgcXVlcnkgc3ludGF4OgorU0VMRUNUIG1pZCBGUk9N
IG1lc3NhZ2UgV0hFUkUgdGFncyBAQCAndXJnZW50ICZhbXA7IGJ1Zyc6OmFueXF1ZXJ5OworCist
LSBNZXNzYWdlcyB0YWdnZWQgJ3VyZ2VudCcgYnV0IG5vdCAnd29udGZpeCc6CitTRUxFQ1QgbWlk
IEZST00gbWVzc2FnZSBXSEVSRSB0YWdzIEBAICd1cmdlbnQgJmFtcDsgIXdvbnRmaXgnOjphbnlx
dWVyeTsKKworLS0gU29ydCBhbmQgZGVkdXBsaWNhdGUgYSB0YWcgbGlzdDoKK1NFTEVDVCBhbnlh
cnJheV91bmlxKHRhZ3MpIEZST00gbWVzc2FnZSBXSEVSRSBtaWQgPSA0MjsKKzwvcHJvZ3JhbWxp
c3Rpbmc+CisgPC9zZWN0Mj4KKworIDxzZWN0MiBpZD0iYW55YXJyYXktYXV0aG9ycyI+CisgIDx0
aXRsZT5BdXRob3JzPC90aXRsZT4KKworICA8cGFyYT4KKyAgIFRoZSA8ZmlsZW5hbWU+YW55YXJy
YXk8L2ZpbGVuYW1lPiBtb2R1bGUgaXMgYSBnZW5lcmFsaXphdGlvbiBvZgorICAgPHhyZWYgbGlu
a2VuZD0iaW50YXJyYXkiLz4gYnkgVGVvZG9yIFNpZ2FldiBhbmQgT2xlZyBCYXJ0dW5vdi4KKyAg
PC9wYXJhPgorIDwvc2VjdDI+CisKKzwvc2VjdDE+CmRpZmYgLS1naXQgYS9kb2Mvc3JjL3NnbWwv
Y29udHJpYi5zZ21sIGIvZG9jL3NyYy9zZ21sL2NvbnRyaWIuc2dtbAppbmRleCBiOWIwMzY1NGFh
ZC4uYzlhYWY3OWNiNjkgMTAwNjQ0Ci0tLSBhL2RvYy9zcmMvc2dtbC9jb250cmliLnNnbWwKKysr
IGIvZG9jL3NyYy9zZ21sL2NvbnRyaWIuc2dtbApAQCAtMTI4LDYgKzEyOCw3IEBAIENSRUFURSBF
WFRFTlNJT04gPHJlcGxhY2VhYmxlPmV4dGVuc2lvbl9uYW1lPC9yZXBsYWNlYWJsZT47CiAgPC9w
YXJhPgogCiAgJmFtY2hlY2s7CisgJmFueWFycmF5OwogICZhdXRoLWRlbGF5OwogICZhdXRvLWV4
cGxhaW47CiAgJmJhc2ViYWNrdXAtdG8tc2hlbGw7CmRpZmYgLS1naXQgYS9kb2Mvc3JjL3NnbWwv
ZmlsZWxpc3Quc2dtbCBiL2RvYy9zcmMvc2dtbC9maWxlbGlzdC5zZ21sCmluZGV4IDI1YTg1MDgy
NzU5Li4wNTMwMzQyZTc0YiAxMDA2NDQKLS0tIGEvZG9jL3NyYy9zZ21sL2ZpbGVsaXN0LnNnbWwK
KysrIGIvZG9jL3NyYy9zZ21sL2ZpbGVsaXN0LnNnbWwKQEAgLTExOSw2ICsxMTksNyBAQAogPCEt
LSBjb250cmliIGluZm9ybWF0aW9uIC0tPgogPCFFTlRJVFkgY29udHJpYiAgICAgICAgIFNZU1RF
TSAiY29udHJpYi5zZ21sIj4KIDwhRU5USVRZIGFtY2hlY2sgICAgICAgICBTWVNURU0gImFtY2hl
Y2suc2dtbCI+Cis8IUVOVElUWSBhbnlhcnJheSAgICAgICAgU1lTVEVNICJhbnlhcnJheS5zZ21s
Ij4KIDwhRU5USVRZIGF1dGgtZGVsYXkgICAgICBTWVNURU0gImF1dGgtZGVsYXkuc2dtbCI+CiA8
IUVOVElUWSBhdXRvLWV4cGxhaW4gICAgU1lTVEVNICJhdXRvLWV4cGxhaW4uc2dtbCI+CiA8IUVO
VElUWSBiYXNpYy1hcmNoaXZlICAgU1lTVEVNICJiYXNpYy1hcmNoaXZlLnNnbWwiPgpkaWZmIC0t
Z2l0IGEvc3JjL3Rvb2xzL3BnaW5kZW50L3R5cGVkZWZzLmxpc3QgYi9zcmMvdG9vbHMvcGdpbmRl
bnQvdHlwZWRlZnMubGlzdAppbmRleCBjYmQ5ZTEwZmMxZC4uMDQ5NDg1ZjVjMjQgMTAwNjQ0Ci0t
LSBhL3NyYy90b29scy9wZ2luZGVudC90eXBlZGVmcy5saXN0CisrKyBiL3NyYy90b29scy9wZ2lu
ZGVudC90eXBlZGVmcy5saXN0CkBAIC0xMjYsNyArMTI2LDEzIEBAIEFuYWx5emVBdHRyRmV0Y2hG
dW5jCiBBbmFseXplRm9yZWlnblRhYmxlX2Z1bmN0aW9uCiBBbmxFeHByRGF0YQogQW5sSW5kZXhE
YXRhCitBbnlBcnJheUdpc3RLZXkKK0FueUFycmF5R2lzdE9wdGlvbnMKIEFueUFycmF5VHlwZQor
QW55QXJyYXlUeXBlSW5mbworQW55UXVlcnkKK0FueVF1ZXJ5Q2hlY2sKK0FueVF1ZXJ5SXRlbQog
QXBwZW5kCiBBcHBlbmRQYXRoCiBBcHBlbmRQYXRoSW5wdXQKQEAgLTE3NDQsNiArMTc1MCw3IEBA
IE1WTkRpc3RpbmN0CiBNVk5EaXN0aW5jdEl0ZW0KIE1hbnlUZXN0UmVzb3VyY2UKIE1hbnlUZXN0
UmVzb3VyY2VLaW5kCitNYXRjaENvbnRleHQKIE1hdGVyaWFsCiBNYXRlcmlhbFBhdGgKIE1hdGVy
aWFsU3RhdGUKQEAgLTIzNzIsNiArMjM3OSw3IEBAIFBnWG1sU3RyaWN0bmVzcwogUGdfYWJpX3Zh
bHVlcwogUGdfZmluZm9fcmVjb3JkCiBQZ19tYWdpY19zdHJ1Y3QKK1BpY2tTcGxpdEVudHJ5CiBQ
aXBlUHJvdG9DaHVuawogUGlwZVByb3RvSGVhZGVyCiBQbGFjZUhvbGRlckluZm8KLS0gCjIuMzku
NSAoQXBwbGUgR2l0LTE1NCkKCg==
------==--bound.57032.6aac6e78-4ced-434c-8f99-30532fa674c1--






Attachments:

  [application/octet-stream] 0001-Add-contrib-anyarray-intarray-style-operations-and-i.patch (135.5K, 2-0001-Add-contrib-anyarray-intarray-style-operations-and-i.patch)
  download | inline diff:
From 0a6e71bbc470fcd0b29e06865bf85d2c8ac148ca Mon Sep 17 00:00:00 2001
From: Vlad Medveditskov <[email protected]>
Date: Mon, 18 May 2026 12:50:13 +0300
Subject: [PATCH] Add contrib/anyarray: intarray-style operations and indexes
 for any array type

This new contrib module generalizes contrib/intarray to arrays of any
element type with a default btree opclass.  It provides:

* Set-style helpers for anyarray / anyelement: anyarray_sort
  (with optional asc/desc direction), anyarray_uniq, anyarray_idx,
  anyarray_subarray (2- and 3-arg), anyarray_icount,
  anyarray_intersect, anyarray_union, anyarray_union_elem,
  anyarray_difference, anyarray_difference_elem, plus the
  corresponding operators #, &, |, - on anyarray and anyelement.

* A textual boolean query type "anyquery" and the operators
  anyarray @@ anyquery (with commutator anyquery ~~ anyarray).
  Tokens are stored as text and parsed lazily through the
  element type's input function at match time, so the same
  query value can be used against arrays of different element
  types.

* A signature-based polymorphic GiST opclass "anyarray_gist_ops"
  on anyarray.  Each indexed array is hashed into a fixed-size
  bit vector; internal nodes store the bitwise union of their
  children, with an ALLISTRUE short-circuit when every bit is
  set.  Signature length is configurable via the siglen
  reloption (default 252 bytes).

* GIN opclasses for the three element types most commonly
  requested by users: int8_anyquery_gin_ops,
  uuid_anyquery_gin_ops and text_anyquery_gin_ops.  They are
  per-concrete-type because the GIN AM does not propagate
  fn_expr into extractQuery, so the element type needed to
  parse anyquery tokens cannot be discovered dynamically.
  Strategies 1-4 mirror the built-in array_ops; strategy 5
  is @@.

* doc/src/sgml/anyarray.sgml with descriptions of every
  function, operator and opclass, plus a usage example.

* Regression test (contrib/anyarray/sql/anyarray.sql,
  expected/anyarray.out) covering int8, uuid and text inputs,
  the error paths, and a cross-AM consistency block that
  asserts seqscan, GiST and GIN return the same row set for
  seven representative predicates.
---
 contrib/Makefile                       |   1 +
 contrib/anyarray/.gitignore            |   4 +
 contrib/anyarray/Makefile              |  27 +
 contrib/anyarray/anyarray--1.0.sql     | 336 +++++++++++
 contrib/anyarray/anyarray.c            | 116 ++++
 contrib/anyarray/anyarray.control      |   6 +
 contrib/anyarray/anyarray.h            | 184 ++++++
 contrib/anyarray/anyarray_bool.c       | 664 ++++++++++++++++++++++
 contrib/anyarray/anyarray_gin.c        | 374 +++++++++++++
 contrib/anyarray/anyarray_gist.c       | 742 +++++++++++++++++++++++++
 contrib/anyarray/anyarray_op.c         | 613 ++++++++++++++++++++
 contrib/anyarray/expected/anyarray.out | 727 ++++++++++++++++++++++++
 contrib/anyarray/meson.build           |  38 ++
 contrib/anyarray/sql/anyarray.sql      | 330 +++++++++++
 contrib/meson.build                    |   1 +
 doc/src/sgml/anyarray.sgml             | 482 ++++++++++++++++
 doc/src/sgml/contrib.sgml              |   1 +
 doc/src/sgml/filelist.sgml             |   1 +
 src/tools/pgindent/typedefs.list       |   8 +
 19 files changed, 4655 insertions(+)
 create mode 100644 contrib/anyarray/.gitignore
 create mode 100644 contrib/anyarray/Makefile
 create mode 100644 contrib/anyarray/anyarray--1.0.sql
 create mode 100644 contrib/anyarray/anyarray.c
 create mode 100644 contrib/anyarray/anyarray.control
 create mode 100644 contrib/anyarray/anyarray.h
 create mode 100644 contrib/anyarray/anyarray_bool.c
 create mode 100644 contrib/anyarray/anyarray_gin.c
 create mode 100644 contrib/anyarray/anyarray_gist.c
 create mode 100644 contrib/anyarray/anyarray_op.c
 create mode 100644 contrib/anyarray/expected/anyarray.out
 create mode 100644 contrib/anyarray/meson.build
 create mode 100644 contrib/anyarray/sql/anyarray.sql
 create mode 100644 doc/src/sgml/anyarray.sgml

diff --git a/contrib/Makefile b/contrib/Makefile
index 7d91fe77db3..b9586cb3a6b 100644
--- a/contrib/Makefile
+++ b/contrib/Makefile
@@ -6,6 +6,7 @@ include $(top_builddir)/src/Makefile.global
 
 SUBDIRS = \
 		amcheck		\
+		anyarray	\
 		auth_delay	\
 		auto_explain	\
 		basic_archive	\
diff --git a/contrib/anyarray/.gitignore b/contrib/anyarray/.gitignore
new file mode 100644
index 00000000000..5dcb3ff9723
--- /dev/null
+++ b/contrib/anyarray/.gitignore
@@ -0,0 +1,4 @@
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/contrib/anyarray/Makefile b/contrib/anyarray/Makefile
new file mode 100644
index 00000000000..d6eb9ae10ad
--- /dev/null
+++ b/contrib/anyarray/Makefile
@@ -0,0 +1,27 @@
+# contrib/anyarray/Makefile
+
+MODULE_big = anyarray
+OBJS = \
+	$(WIN32RES) \
+	anyarray.o \
+	anyarray_bool.o \
+	anyarray_gin.o \
+	anyarray_gist.o \
+	anyarray_op.o
+
+EXTENSION = anyarray
+DATA = anyarray--1.0.sql
+PGFILEDESC = "anyarray - operations and indexes for arrays of any type"
+
+REGRESS = anyarray
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = contrib/anyarray
+top_builddir = ../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/contrib/anyarray/anyarray--1.0.sql b/contrib/anyarray/anyarray--1.0.sql
new file mode 100644
index 00000000000..84bcff34b5b
--- /dev/null
+++ b/contrib/anyarray/anyarray--1.0.sql
@@ -0,0 +1,336 @@
+/* contrib/anyarray/anyarray--1.0.sql */
+
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION anyarray" to load this file. \quit
+
+--
+-- Set-style operations for arrays of any btree-orderable element type.
+--
+
+CREATE FUNCTION anyarray_sort(anyarray)
+RETURNS anyarray
+AS 'MODULE_PATHNAME', 'anyarray_sort'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE FUNCTION anyarray_sort(anyarray, text)
+RETURNS anyarray
+AS 'MODULE_PATHNAME', 'anyarray_sort_dir'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE FUNCTION anyarray_uniq(anyarray)
+RETURNS anyarray
+AS 'MODULE_PATHNAME', 'anyarray_uniq'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE FUNCTION anyarray_idx(anyarray, anyelement)
+RETURNS int4
+AS 'MODULE_PATHNAME', 'anyarray_idx'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE FUNCTION anyarray_subarray(anyarray, int4, int4)
+RETURNS anyarray
+AS 'MODULE_PATHNAME', 'anyarray_subarray'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE FUNCTION anyarray_subarray(anyarray, int4)
+RETURNS anyarray
+AS 'MODULE_PATHNAME', 'anyarray_subarray_to_end'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE FUNCTION anyarray_icount(anyarray)
+RETURNS int4
+AS 'MODULE_PATHNAME', 'anyarray_icount'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE FUNCTION anyarray_intersect(anyarray, anyarray)
+RETURNS anyarray
+AS 'MODULE_PATHNAME', 'anyarray_intersect'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE FUNCTION anyarray_union(anyarray, anyarray)
+RETURNS anyarray
+AS 'MODULE_PATHNAME', 'anyarray_union'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE FUNCTION anyarray_union_elem(anyarray, anyelement)
+RETURNS anyarray
+AS 'MODULE_PATHNAME', 'anyarray_union_elem'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE FUNCTION anyarray_difference(anyarray, anyarray)
+RETURNS anyarray
+AS 'MODULE_PATHNAME', 'anyarray_difference'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE FUNCTION anyarray_difference_elem(anyarray, anyelement)
+RETURNS anyarray
+AS 'MODULE_PATHNAME', 'anyarray_difference_elem'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+--
+-- Operators
+--
+
+-- Unary prefix # : cardinality (number of elements)
+CREATE OPERATOR # (
+	RIGHTARG = anyarray,
+	PROCEDURE = anyarray_icount
+);
+
+-- array # element : 1-based index of element, or 0 if not found
+CREATE OPERATOR # (
+	LEFTARG = anyarray,
+	RIGHTARG = anyelement,
+	PROCEDURE = anyarray_idx
+);
+
+-- Set intersection
+CREATE OPERATOR & (
+	LEFTARG = anyarray,
+	RIGHTARG = anyarray,
+	COMMUTATOR = &,
+	PROCEDURE = anyarray_intersect
+);
+
+-- Set union (array | array)
+CREATE OPERATOR | (
+	LEFTARG = anyarray,
+	RIGHTARG = anyarray,
+	COMMUTATOR = |,
+	PROCEDURE = anyarray_union
+);
+
+-- Append element (array | element)
+CREATE OPERATOR | (
+	LEFTARG = anyarray,
+	RIGHTARG = anyelement,
+	PROCEDURE = anyarray_union_elem
+);
+
+-- Set difference (array - array)
+CREATE OPERATOR - (
+	LEFTARG = anyarray,
+	RIGHTARG = anyarray,
+	PROCEDURE = anyarray_difference
+);
+
+-- Remove all occurrences of element (array - element)
+CREATE OPERATOR - (
+	LEFTARG = anyarray,
+	RIGHTARG = anyelement,
+	PROCEDURE = anyarray_difference_elem
+);
+
+--
+-- Boolean query type
+--
+
+CREATE FUNCTION anyquery_in(cstring)
+RETURNS anyquery
+AS 'MODULE_PATHNAME', 'anyquery_in'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE FUNCTION anyquery_out(anyquery)
+RETURNS cstring
+AS 'MODULE_PATHNAME', 'anyquery_out'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE TYPE anyquery (
+	INTERNALLENGTH = -1,
+	INPUT = anyquery_in,
+	OUTPUT = anyquery_out,
+	STORAGE = extended
+);
+
+CREATE FUNCTION anyquery_querytree(anyquery)
+RETURNS text
+AS 'MODULE_PATHNAME', 'anyquery_querytree'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE FUNCTION anyarray_boolop(anyarray, anyquery)
+RETURNS bool
+AS 'MODULE_PATHNAME', 'anyarray_boolop'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE FUNCTION anyquery_boolop_rev(anyquery, anyarray)
+RETURNS bool
+AS 'MODULE_PATHNAME', 'anyquery_boolop_rev'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE OPERATOR @@ (
+	LEFTARG = anyarray,
+	RIGHTARG = anyquery,
+	PROCEDURE = anyarray_boolop,
+	COMMUTATOR = '~~',
+	RESTRICT = contsel,
+	JOIN = contjoinsel
+);
+
+CREATE OPERATOR ~~ (
+	LEFTARG = anyquery,
+	RIGHTARG = anyarray,
+	PROCEDURE = anyquery_boolop_rev,
+	COMMUTATOR = '@@',
+	RESTRICT = contsel,
+	JOIN = contjoinsel
+);
+
+--
+-- GiST opclass (signature-based)
+--
+
+CREATE FUNCTION anyarray_gist_key_in(cstring)
+RETURNS anyarray_gist_key
+AS 'MODULE_PATHNAME', 'anyarray_gist_key_in'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE FUNCTION anyarray_gist_key_out(anyarray_gist_key)
+RETURNS cstring
+AS 'MODULE_PATHNAME', 'anyarray_gist_key_out'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
+CREATE TYPE anyarray_gist_key (
+	INTERNALLENGTH = -1,
+	INPUT = anyarray_gist_key_in,
+	OUTPUT = anyarray_gist_key_out
+);
+
+CREATE FUNCTION anyarray_gist_consistent(internal, anyarray, smallint, oid, internal)
+RETURNS bool
+AS 'MODULE_PATHNAME', 'anyarray_gist_consistent'
+LANGUAGE C IMMUTABLE PARALLEL SAFE;
+
+CREATE FUNCTION anyarray_gist_compress(internal)
+RETURNS internal
+AS 'MODULE_PATHNAME', 'anyarray_gist_compress'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE FUNCTION anyarray_gist_decompress(internal)
+RETURNS internal
+AS 'MODULE_PATHNAME', 'anyarray_gist_decompress'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE FUNCTION anyarray_gist_union(internal, internal)
+RETURNS anyarray_gist_key
+AS 'MODULE_PATHNAME', 'anyarray_gist_union'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE FUNCTION anyarray_gist_same(anyarray_gist_key, anyarray_gist_key, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME', 'anyarray_gist_same'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE FUNCTION anyarray_gist_penalty(internal, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME', 'anyarray_gist_penalty'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE FUNCTION anyarray_gist_picksplit(internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME', 'anyarray_gist_picksplit'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE FUNCTION anyarray_gist_options(internal)
+RETURNS void
+AS 'MODULE_PATHNAME', 'anyarray_gist_options'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE OPERATOR CLASS anyarray_gist_ops
+FOR TYPE anyarray USING gist
+AS
+	OPERATOR	3	&&,
+	OPERATOR	7	@>,
+	OPERATOR	8	<@,
+	OPERATOR	18	=,
+	OPERATOR	20	@@ (anyarray, anyquery),
+	FUNCTION	1	anyarray_gist_consistent(internal, anyarray, smallint, oid, internal),
+	FUNCTION	2	anyarray_gist_union(internal, internal),
+	FUNCTION	3	anyarray_gist_compress(internal),
+	FUNCTION	4	anyarray_gist_decompress(internal),
+	FUNCTION	5	anyarray_gist_penalty(internal, internal, internal),
+	FUNCTION	6	anyarray_gist_picksplit(internal, internal),
+	FUNCTION	7	anyarray_gist_same(anyarray_gist_key, anyarray_gist_key, internal),
+	FUNCTION	10	anyarray_gist_options(internal),
+	STORAGE		anyarray_gist_key;
+
+--
+-- GIN opclasses (per concrete element type, supporting standard ops + @@)
+--
+
+CREATE FUNCTION anyarray_gin_extract_query_int8(
+	int8[], internal, smallint, internal, internal, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME', 'anyarray_gin_extract_query_int8'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE FUNCTION anyarray_gin_consistent_int8(
+	internal, smallint, int8[], integer, internal, internal, internal, internal)
+RETURNS bool
+AS 'MODULE_PATHNAME', 'anyarray_gin_consistent_int8'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE OPERATOR CLASS int8_anyquery_gin_ops
+FOR TYPE int8[] USING gin
+AS
+	OPERATOR	1	&& (anyarray, anyarray),
+	OPERATOR	2	@> (anyarray, anyarray),
+	OPERATOR	3	<@ (anyarray, anyarray),
+	OPERATOR	4	= (anyarray, anyarray),
+	OPERATOR	5	@@ (anyarray, anyquery),
+	FUNCTION	1	btint8cmp(int8, int8),
+	FUNCTION	2	ginarrayextract(anyarray, internal, internal),
+	FUNCTION	3	anyarray_gin_extract_query_int8(int8[], internal, smallint, internal, internal, internal, internal),
+	FUNCTION	4	anyarray_gin_consistent_int8(internal, smallint, int8[], integer, internal, internal, internal, internal),
+	STORAGE		int8;
+
+CREATE FUNCTION anyarray_gin_extract_query_uuid(
+	uuid[], internal, smallint, internal, internal, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME', 'anyarray_gin_extract_query_uuid'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE FUNCTION anyarray_gin_consistent_uuid(
+	internal, smallint, uuid[], integer, internal, internal, internal, internal)
+RETURNS bool
+AS 'MODULE_PATHNAME', 'anyarray_gin_consistent_uuid'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE OPERATOR CLASS uuid_anyquery_gin_ops
+FOR TYPE uuid[] USING gin
+AS
+	OPERATOR	1	&& (anyarray, anyarray),
+	OPERATOR	2	@> (anyarray, anyarray),
+	OPERATOR	3	<@ (anyarray, anyarray),
+	OPERATOR	4	= (anyarray, anyarray),
+	OPERATOR	5	@@ (anyarray, anyquery),
+	FUNCTION	1	uuid_cmp(uuid, uuid),
+	FUNCTION	2	ginarrayextract(anyarray, internal, internal),
+	FUNCTION	3	anyarray_gin_extract_query_uuid(uuid[], internal, smallint, internal, internal, internal, internal),
+	FUNCTION	4	anyarray_gin_consistent_uuid(internal, smallint, uuid[], integer, internal, internal, internal, internal),
+	STORAGE		uuid;
+
+CREATE FUNCTION anyarray_gin_extract_query_text(
+	text[], internal, smallint, internal, internal, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME', 'anyarray_gin_extract_query_text'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE FUNCTION anyarray_gin_consistent_text(
+	internal, smallint, text[], integer, internal, internal, internal, internal)
+RETURNS bool
+AS 'MODULE_PATHNAME', 'anyarray_gin_consistent_text'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE OPERATOR CLASS text_anyquery_gin_ops
+FOR TYPE text[] USING gin
+AS
+	OPERATOR	1	&& (anyarray, anyarray),
+	OPERATOR	2	@> (anyarray, anyarray),
+	OPERATOR	3	<@ (anyarray, anyarray),
+	OPERATOR	4	= (anyarray, anyarray),
+	OPERATOR	5	@@ (anyarray, anyquery),
+	FUNCTION	1	bttextcmp(text, text),
+	FUNCTION	2	ginarrayextract(anyarray, internal, internal),
+	FUNCTION	3	anyarray_gin_extract_query_text(text[], internal, smallint, internal, internal, internal, internal),
+	FUNCTION	4	anyarray_gin_consistent_text(internal, smallint, text[], integer, internal, internal, internal, internal),
+	STORAGE		text;
diff --git a/contrib/anyarray/anyarray.c b/contrib/anyarray/anyarray.c
new file mode 100644
index 00000000000..0a2ab2153c8
--- /dev/null
+++ b/contrib/anyarray/anyarray.c
@@ -0,0 +1,116 @@
+/*-------------------------------------------------------------------------
+ *
+ * anyarray.c
+ *		Common code for the anyarray extension.
+ *
+ * This extension extends PostgreSQL with intarray-style operations and
+ * index support that work for arrays of any element type with a default
+ * btree opclass.  It is a generalization of the contrib/intarray module.
+ *
+ * Copyright (c) 2026, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *		contrib/anyarray/anyarray.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "anyarray.h"
+#include "catalog/pg_type.h"
+#include "utils/builtins.h"
+#include "utils/lsyscache.h"
+
+PG_MODULE_MAGIC_EXT(
+					.name = "anyarray",
+					.version = PG_VERSION
+);
+
+/*
+ * anyarray_get_meta
+ *		Fetch (and cache) type metadata for the given element type.
+ *
+ * The cache lives in fcinfo->flinfo->fn_extra so we pay the catalog lookup
+ * cost only once per call site.  If "need_hash" is true the element type
+ * must additionally provide a default hash function; otherwise only a btree
+ * comparison function is required.
+ */
+AnyArrayTypeInfo *
+anyarray_get_meta(FunctionCallInfo fcinfo, Oid element_type, bool need_hash)
+{
+	AnyArrayTypeInfo *meta = (AnyArrayTypeInfo *) fcinfo->flinfo->fn_extra;
+	TypeCacheEntry *typentry;
+	uint32		flags;
+
+	if (meta == NULL)
+	{
+		meta = (AnyArrayTypeInfo *)
+			MemoryContextAllocZero(fcinfo->flinfo->fn_mcxt,
+								   sizeof(AnyArrayTypeInfo));
+		fcinfo->flinfo->fn_extra = meta;
+		meta->element_type = InvalidOid;
+	}
+
+	if (meta->element_type == element_type && (!need_hash || meta->have_hash))
+		return meta;
+
+	flags = TYPECACHE_CMP_PROC_FINFO | TYPECACHE_EQ_OPR_FINFO;
+	if (need_hash)
+		flags |= TYPECACHE_HASH_PROC_FINFO;
+
+	typentry = lookup_type_cache(element_type, flags);
+
+	if (!OidIsValid(typentry->cmp_proc_finfo.fn_oid))
+		ereport(ERROR,
+				(errcode(ERRCODE_UNDEFINED_FUNCTION),
+				 errmsg("could not identify a comparison function for type %s",
+						format_type_be(element_type))));
+
+	if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
+		ereport(ERROR,
+				(errcode(ERRCODE_UNDEFINED_FUNCTION),
+				 errmsg("could not identify an equality operator for type %s",
+						format_type_be(element_type))));
+
+	if (need_hash && !OidIsValid(typentry->hash_proc_finfo.fn_oid))
+		ereport(ERROR,
+				(errcode(ERRCODE_UNDEFINED_FUNCTION),
+				 errmsg("could not identify a hash function for type %s",
+						format_type_be(element_type))));
+
+	meta->element_type = element_type;
+	get_typlenbyvalalign(element_type, &meta->typlen, &meta->typbyval,
+						 &meta->typalign);
+	meta->typcollation = typentry->typcollation;
+	fmgr_info_cxt(typentry->cmp_proc_finfo.fn_oid, &meta->cmp_proc,
+				  fcinfo->flinfo->fn_mcxt);
+	fmgr_info_cxt(typentry->eq_opr_finfo.fn_oid, &meta->eq_proc,
+				  fcinfo->flinfo->fn_mcxt);
+	if (need_hash)
+	{
+		fmgr_info_cxt(typentry->hash_proc_finfo.fn_oid, &meta->hash_proc,
+					  fcinfo->flinfo->fn_mcxt);
+		meta->have_hash = true;
+	}
+	else
+		meta->have_hash = false;
+
+	return meta;
+}
+
+/*
+ * anyarray_cmp_datum
+ *		qsort_arg-compatible comparator delegating to the type's btree cmp.
+ */
+int
+anyarray_cmp_datum(const void *a, const void *b, void *arg)
+{
+	AnyArrayTypeInfo *meta = (AnyArrayTypeInfo *) arg;
+	Datum		d1 = *((const Datum *) a);
+	Datum		d2 = *((const Datum *) b);
+	Datum		result;
+
+	result = FunctionCall2Coll(&meta->cmp_proc, meta->typcollation, d1, d2);
+	return DatumGetInt32(result);
+}
diff --git a/contrib/anyarray/anyarray.control b/contrib/anyarray/anyarray.control
new file mode 100644
index 00000000000..2478f2d93d7
--- /dev/null
+++ b/contrib/anyarray/anyarray.control
@@ -0,0 +1,6 @@
+# anyarray extension
+comment = 'Operations and indexes for arrays of any type'
+default_version = '1.0'
+module_pathname = '$libdir/anyarray'
+relocatable = true
+trusted = false
diff --git a/contrib/anyarray/anyarray.h b/contrib/anyarray/anyarray.h
new file mode 100644
index 00000000000..f59ac9de749
--- /dev/null
+++ b/contrib/anyarray/anyarray.h
@@ -0,0 +1,184 @@
+/*-------------------------------------------------------------------------
+ *
+ * anyarray.h
+ *		Shared declarations for the anyarray extension.
+ *
+ * Copyright (c) 2026, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *		contrib/anyarray/anyarray.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef ANYARRAY_H
+#define ANYARRAY_H
+
+#include "access/gist.h"
+#include "fmgr.h"
+#include "utils/array.h"
+#include "utils/typcache.h"
+
+/*
+ * Per-call cached element type metadata.
+ *
+ * Stored in fcinfo->flinfo->fn_extra so we look up the type once per
+ * planner-level call site.  All entries are populated by anyarray_get_meta().
+ */
+typedef struct AnyArrayTypeInfo
+{
+	Oid			element_type;	/* element OID, or InvalidOid if not
+								 * initialized */
+	int16		typlen;
+	bool		typbyval;
+	char		typalign;
+	Oid			typcollation;	/* default collation for comparisons */
+	FmgrInfo	cmp_proc;		/* btree comparison function for element_type */
+	FmgrInfo	eq_proc;		/* equality function for element_type */
+	FmgrInfo	hash_proc;		/* hash function for element_type (optional) */
+	bool		have_hash;		/* whether hash_proc was filled in */
+} AnyArrayTypeInfo;
+
+/* Reject the kinds of input we do not handle. */
+#define ANYARRAY_CHECK_ARRAY(arr) \
+	do { \
+		if (ARR_NDIM(arr) > 1) \
+			ereport(ERROR, \
+					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), \
+					 errmsg("multidimensional arrays are not supported"))); \
+		if (ARR_HASNULL(arr) && array_contains_nulls(arr)) \
+			ereport(ERROR, \
+					(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), \
+					 errmsg("array must not contain nulls"))); \
+	} while (0)
+
+#define ANYARRAY_NELEMS(arr) \
+	(ARR_NDIM(arr) > 0 ? ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr)) : 0)
+
+/*
+ * Initialize / refresh AnyArrayTypeInfo for a given element type.
+ *
+ * Allocates the struct in fcinfo->flinfo->fn_mcxt on first use; on subsequent
+ * calls reuses the cache unless the element type changed.  Reports an error
+ * via ereport() if the element type lacks a btree comparison operator
+ * (need_hash == true additionally requires a hash function).
+ */
+extern AnyArrayTypeInfo *anyarray_get_meta(FunctionCallInfo fcinfo,
+										   Oid element_type,
+										   bool need_hash);
+
+/*
+ * Comparison helper used both as a qsort_arg callback and directly.
+ * "arg" must be a valid AnyArrayTypeInfo *.
+ */
+extern int	anyarray_cmp_datum(const void *a, const void *b, void *arg);
+
+/*****************************************************************************
+ *  Boolean query type
+ *
+ *  An anyquery value is a boolean expression in postfix notation whose leaves
+ *  are textual representations of values.  The element type is not known at
+ *  parse time; it is supplied at @@-time by the array operand, and the value
+ *  strings are parsed lazily through the element type's text input function.
+ *
+ *  On-disk layout:
+ *
+ *     +-----------------------------+
+ *     | varlena header              |
+ *     | int32  size      (n items)  |
+ *     | int32  str_off              |  -- byte offset to string heap
+ *     | int32  str_len              |
+ *     | AnyQueryItem items[size]    |
+ *     | <padding>                   |
+ *     | char   strings[str_len]     |  -- null-terminated value strings
+ *     +-----------------------------+
+ *****************************************************************************/
+
+/* item.type values */
+#define ANYQ_VAL	1
+#define ANYQ_OPR	2
+
+/* operator codes (also used in the input grammar) */
+#define ANYQ_AND	'&'
+#define ANYQ_OR		'|'
+#define ANYQ_NOT	'!'
+
+typedef struct AnyQueryItem
+{
+	int16		type;			/* ANYQ_VAL or ANYQ_OPR */
+	int16		left;			/* offset to left-operand item (OPR only) */
+	int32		payload;		/* VAL: offset into string heap; OPR: one of
+								 * ANYQ_AND/OR/NOT */
+} AnyQueryItem;
+
+typedef struct AnyQuery
+{
+	int32		vl_len_;		/* varlena header (do not touch directly!) */
+	int32		size;			/* number of items */
+	int32		str_off;		/* byte offset to string heap */
+	int32		str_len;		/* length of string heap */
+	AnyQueryItem items[FLEXIBLE_ARRAY_MEMBER];
+	/* followed by null-terminated value strings */
+} AnyQuery;
+
+#define ANYQUERY_HDRSIZE			offsetof(AnyQuery, items)
+#define ANYQUERY_ITEMS(q)			((q)->items)
+#define ANYQUERY_STRING(q, item)	((const char *) (q) + (q)->str_off + (item)->payload)
+#define ANYQUERY_MAXITEMS \
+	((MaxAllocSize - ANYQUERY_HDRSIZE) / sizeof(AnyQueryItem))
+
+#define DatumGetAnyQueryP(X)		((AnyQuery *) PG_DETOAST_DATUM(X))
+#define PG_GETARG_ANYQUERY_P(n)		DatumGetAnyQueryP(PG_GETARG_DATUM(n))
+
+/*****************************************************************************
+ *  GiST signature key
+ *
+ *  Each indexed array is summarized as a fixed-size bit vector ("signature").
+ *  Each element contributes a single bit, chosen as
+ *      hash(element) mod (siglen * 8).
+ *  Internal node keys are bitwise unions of their children; the ALLISTRUE
+ *  flag short-circuits storage when every bit would be set.
+ *****************************************************************************/
+
+#define ANYARRAY_SIGLEN_DEFAULT		(63 * 4)	/* 252 bytes -> 2016 bits */
+#define ANYARRAY_SIGLEN_MAX			GISTMaxIndexKeySize
+#define ANYARRAY_ALLISTRUE			0x01
+
+typedef struct AnyArrayGistKey
+{
+	int32		vl_len_;		/* varlena header (do not touch directly!) */
+	int32		flag;
+	char		data[FLEXIBLE_ARRAY_MEMBER];	/* bit vector, siglen bytes */
+} AnyArrayGistKey;
+
+typedef struct AnyArrayGistOptions
+{
+	int32		vl_len_;
+	int			siglen;			/* signature length in bytes */
+} AnyArrayGistOptions;
+
+#define ANYARRAY_GET_SIGLEN()		(PG_HAS_OPCLASS_OPTIONS() ? \
+									 ((AnyArrayGistOptions *) PG_GET_OPCLASS_OPTIONS())->siglen : \
+									 ANYARRAY_SIGLEN_DEFAULT)
+
+#define ANYARRAY_GKEY_HDR			(VARHDRSZ + sizeof(int32))
+#define ANYARRAY_GKEY_SIZE(flag, siglen) \
+	(ANYARRAY_GKEY_HDR + (((flag) & ANYARRAY_ALLISTRUE) ? 0 : (siglen)))
+#define ANYARRAY_GKEY_ISALLTRUE(k)	(((AnyArrayGistKey *) (k))->flag & ANYARRAY_ALLISTRUE)
+#define ANYARRAY_GKEY_SIGN(k)		((unsigned char *) (((AnyArrayGistKey *) (k))->data))
+
+/* GIN strategy numbers; the first four match core's gin/array_ops */
+#define ANYARRAY_GIN_OVERLAP_STRATEGY	1
+#define ANYARRAY_GIN_CONTAINS_STRATEGY	2
+#define ANYARRAY_GIN_CONTAINED_STRATEGY	3
+#define ANYARRAY_GIN_EQUAL_STRATEGY		4
+#define ANYARRAY_GIN_BOOLEAN_STRATEGY	5
+
+#define ANYARRAY_HASHVAL(h, siglen)	((unsigned int) (h) % ((siglen) * BITS_PER_BYTE))
+#define ANYARRAY_SETBIT(sig, h, siglen) \
+	((sig)[(ANYARRAY_HASHVAL((h), (siglen)) / BITS_PER_BYTE)] |= \
+		(1 << (ANYARRAY_HASHVAL((h), (siglen)) % BITS_PER_BYTE)))
+#define ANYARRAY_GETBIT(sig, h, siglen) \
+	(((sig)[(ANYARRAY_HASHVAL((h), (siglen)) / BITS_PER_BYTE)] >> \
+		(ANYARRAY_HASHVAL((h), (siglen)) % BITS_PER_BYTE)) & 1)
+
+#endif							/* ANYARRAY_H */
diff --git a/contrib/anyarray/anyarray_bool.c b/contrib/anyarray/anyarray_bool.c
new file mode 100644
index 00000000000..325619837ef
--- /dev/null
+++ b/contrib/anyarray/anyarray_bool.c
@@ -0,0 +1,664 @@
+/*-------------------------------------------------------------------------
+ *
+ * anyarray_bool.c
+ *		Boolean query type for anyarray.
+ *
+ * Provides the anyquery type and the @@ operator.  A query value is a
+ * boolean expression whose leaves are text tokens; the element type is
+ * supplied at @@-time by the array operand, and the leaves are parsed
+ * through the element type's text input function.
+ *
+ * Grammar:
+ *
+ *	  expr        ::= or_expr
+ *	  or_expr     ::= and_expr ( '|' and_expr )*
+ *	  and_expr    ::= unary_expr ( '&' unary_expr )*
+ *	  unary_expr  ::= '!' unary_expr | atom
+ *	  atom        ::= VALUE | '(' expr ')'
+ *	  VALUE       ::= bare_token | quoted_string
+ *	  bare_token  ::= any run of characters that are not whitespace,
+ *	                  '&', '|', '!', '(', ')', or '"'
+ *	  quoted_string := '"' chars-with-backslash-escapes '"'
+ *
+ *
+ * Copyright (c) 2026, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *		contrib/anyarray/anyarray_bool.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "anyarray.h"
+
+#include "lib/stringinfo.h"
+#include "miscadmin.h"
+#include "nodes/miscnodes.h"
+#include "utils/array.h"
+#include "utils/builtins.h"
+#include "utils/lsyscache.h"
+#include "utils/memutils.h"
+
+PG_FUNCTION_INFO_V1(anyquery_in);
+PG_FUNCTION_INFO_V1(anyquery_out);
+PG_FUNCTION_INFO_V1(anyarray_boolop);
+PG_FUNCTION_INFO_V1(anyquery_boolop_rev);
+PG_FUNCTION_INFO_V1(anyquery_querytree);
+
+
+/* ------------------------------------------------------------------------
+ *  Parser
+ * ------------------------------------------------------------------------
+ */
+
+/*
+ * Working state used while building the postfix item list.
+ *
+ * Items are emitted in postfix (reverse polish) order directly into the
+ * "items" array.  Value strings are concatenated into "strs"; each VAL item
+ * stores the byte offset of its string within strs->data.
+ */
+typedef struct ParserState
+{
+	const char *cur;
+	const char *end;
+	AnyQueryItem *items;
+	int			nitems;
+	int			capitems;
+	StringInfoData strs;
+	struct Node *escontext;
+} ParserState;
+
+#define PARSE_FAIL(state, errc, ...) \
+	do { \
+		errsave((state)->escontext, \
+				(errcode(errc), \
+				 __VA_ARGS__)); \
+		return false; \
+	} while (0)
+
+static bool parse_expr(ParserState *state);
+
+static void
+skip_ws(ParserState *state)
+{
+	while (state->cur < state->end &&
+		   (*state->cur == ' ' || *state->cur == '\t' ||
+			*state->cur == '\r' || *state->cur == '\n' ||
+			*state->cur == '\v' || *state->cur == '\f'))
+		state->cur++;
+}
+
+static bool
+is_value_char(char c)
+{
+	if (c == '\0' || c == ' ' || c == '\t' || c == '\r' || c == '\n' ||
+		c == '\v' || c == '\f')
+		return false;
+	if (c == '&' || c == '|' || c == '!' || c == '(' || c == ')' || c == '"')
+		return false;
+	return true;
+}
+
+static bool
+emit_item(ParserState *state, int16 type, int32 payload)
+{
+	if (state->nitems == state->capitems)
+	{
+		if ((size_t) state->capitems * 2 > ANYQUERY_MAXITEMS)
+			PARSE_FAIL(state, ERRCODE_PROGRAM_LIMIT_EXCEEDED,
+					   errmsg("anyquery expression is too complex"));
+		state->capitems *= 2;
+		state->items = (AnyQueryItem *) repalloc(state->items,
+												 sizeof(AnyQueryItem) *
+												 state->capitems);
+	}
+	state->items[state->nitems].type = type;
+	state->items[state->nitems].left = 0;
+	state->items[state->nitems].payload = payload;
+	state->nitems++;
+	return true;
+}
+
+/*
+ * Consume a value token, append its string (with terminating NUL) to
+ * state->strs, and emit a VAL item whose payload is the byte offset of the
+ * string within strs->data.
+ */
+static bool
+parse_value(ParserState *state)
+{
+	int32		off;
+
+	skip_ws(state);
+
+	if (state->cur >= state->end)
+		PARSE_FAIL(state, ERRCODE_SYNTAX_ERROR,
+				   errmsg("unexpected end of input in anyquery"));
+
+	off = state->strs.len;
+
+	if (*state->cur == '"')
+	{
+		state->cur++;			/* opening quote */
+		while (state->cur < state->end && *state->cur != '"')
+		{
+			if (*state->cur == '\\' && state->cur + 1 < state->end)
+				state->cur++;
+			appendStringInfoChar(&state->strs, *state->cur);
+			state->cur++;
+		}
+		if (state->cur >= state->end)
+			PARSE_FAIL(state, ERRCODE_SYNTAX_ERROR,
+					   errmsg("unterminated quoted value in anyquery"));
+		state->cur++;			/* closing quote */
+	}
+	else if (is_value_char(*state->cur))
+	{
+		while (state->cur < state->end && is_value_char(*state->cur))
+		{
+			appendStringInfoChar(&state->strs, *state->cur);
+			state->cur++;
+		}
+	}
+	else
+		PARSE_FAIL(state, ERRCODE_SYNTAX_ERROR,
+				   errmsg("expected value at character \"%c\"", *state->cur));
+
+	appendStringInfoChar(&state->strs, '\0');
+	return emit_item(state, ANYQ_VAL, off);
+}
+
+static bool
+parse_atom(ParserState *state)
+{
+	skip_ws(state);
+	if (state->cur < state->end && *state->cur == '(')
+	{
+		state->cur++;
+		if (!parse_expr(state))
+			return false;
+		skip_ws(state);
+		if (state->cur >= state->end || *state->cur != ')')
+			PARSE_FAIL(state, ERRCODE_SYNTAX_ERROR,
+					   errmsg("missing closing parenthesis in anyquery"));
+		state->cur++;
+		return true;
+	}
+	return parse_value(state);
+}
+
+static bool
+parse_not(ParserState *state)
+{
+	skip_ws(state);
+	if (state->cur < state->end && *state->cur == '!')
+	{
+		state->cur++;
+		if (!parse_not(state))
+			return false;
+		return emit_item(state, ANYQ_OPR, ANYQ_NOT);
+	}
+	return parse_atom(state);
+}
+
+static bool
+parse_and(ParserState *state)
+{
+	if (!parse_not(state))
+		return false;
+	for (;;)
+	{
+		skip_ws(state);
+		if (state->cur >= state->end || *state->cur != '&')
+			return true;
+		state->cur++;
+		if (!parse_not(state))
+			return false;
+		if (!emit_item(state, ANYQ_OPR, ANYQ_AND))
+			return false;
+	}
+}
+
+static bool
+parse_expr(ParserState *state)
+{
+	check_stack_depth();
+
+	if (!parse_and(state))
+		return false;
+	for (;;)
+	{
+		skip_ws(state);
+		if (state->cur >= state->end || *state->cur != '|')
+			return true;
+		state->cur++;
+		if (!parse_and(state))
+			return false;
+		if (!emit_item(state, ANYQ_OPR, ANYQ_OR))
+			return false;
+	}
+}
+
+/*
+ * Compute the "left" field for every OPR item by walking the postfix array
+ * top-down.  Returns false on overflow of the int16 left field.
+ */
+static bool
+compute_lefts(ParserState *state, int *pos)
+{
+	int			mypos;
+
+	check_stack_depth();
+
+	mypos = (*pos)--;
+	Assert(mypos >= 0);
+
+	if (state->items[mypos].type == ANYQ_VAL)
+	{
+		state->items[mypos].left = 0;
+		return true;
+	}
+	else if (state->items[mypos].payload == ANYQ_NOT)
+	{
+		state->items[mypos].left = -1;
+		return compute_lefts(state, pos);
+	}
+	else
+	{
+		int			delta;
+
+		/* binary operator: walk right operand */
+		if (!compute_lefts(state, pos))
+			return false;
+		delta = *pos - mypos;
+		if (delta < PG_INT16_MIN)
+		{
+			errsave(state->escontext,
+					(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+					 errmsg("anyquery expression is too complex")));
+			return false;
+		}
+		state->items[mypos].left = (int16) delta;
+		return compute_lefts(state, pos);
+	}
+}
+
+
+/* ------------------------------------------------------------------------
+ *  Input / output / debug
+ * ------------------------------------------------------------------------
+ */
+
+Datum
+anyquery_in(PG_FUNCTION_ARGS)
+{
+	char	   *buf = PG_GETARG_CSTRING(0);
+	ParserState state;
+	AnyQuery   *out;
+	Size		items_bytes;
+	Size		total;
+	int			pos;
+
+	state.cur = buf;
+	state.end = buf + strlen(buf);
+	state.capitems = 16;
+	state.items = (AnyQueryItem *) palloc(sizeof(AnyQueryItem) *
+										  state.capitems);
+	state.nitems = 0;
+	initStringInfo(&state.strs);
+	state.escontext = fcinfo->context;
+
+	if (!parse_expr(&state))
+		PG_RETURN_NULL();
+
+	skip_ws(&state);
+	if (state.cur < state.end)
+		ereturn(state.escontext, (Datum) 0,
+				(errcode(ERRCODE_SYNTAX_ERROR),
+				 errmsg("unexpected trailing input in anyquery")));
+
+	if (state.nitems == 0)
+		ereturn(state.escontext, (Datum) 0,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("empty anyquery")));
+
+	if ((size_t) state.nitems > ANYQUERY_MAXITEMS)
+		ereturn(state.escontext, (Datum) 0,
+				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+				 errmsg("anyquery has too many items (%d, maximum %zu)",
+						state.nitems, ANYQUERY_MAXITEMS)));
+
+	pos = state.nitems - 1;
+	if (!compute_lefts(&state, &pos))
+		PG_RETURN_NULL();
+	Assert(pos == -1);
+
+	items_bytes = MAXALIGN(state.nitems * sizeof(AnyQueryItem));
+	total = ANYQUERY_HDRSIZE + items_bytes + state.strs.len;
+
+	out = (AnyQuery *) palloc0(total);
+	SET_VARSIZE(out, total);
+	out->size = state.nitems;
+	out->str_off = ANYQUERY_HDRSIZE + items_bytes;
+	out->str_len = state.strs.len;
+	memcpy(out->items, state.items, state.nitems * sizeof(AnyQueryItem));
+	memcpy((char *) out + out->str_off, state.strs.data, state.strs.len);
+
+	pfree(state.items);
+	pfree(state.strs.data);
+
+	PG_RETURN_POINTER(out);
+}
+
+/*
+ * Quote a value string if it contains anything the parser would consider
+ * special.  Otherwise emit it verbatim.
+ */
+static void
+append_value_token(StringInfo out, const char *s)
+{
+	const char *p;
+	bool		need_quote = (*s == '\0');
+
+	for (p = s; *p; p++)
+	{
+		if (!is_value_char(*p))
+		{
+			need_quote = true;
+			break;
+		}
+	}
+
+	if (!need_quote)
+	{
+		appendStringInfoString(out, s);
+		return;
+	}
+
+	appendStringInfoChar(out, '"');
+	for (p = s; *p; p++)
+	{
+		if (*p == '"' || *p == '\\')
+			appendStringInfoChar(out, '\\');
+		appendStringInfoChar(out, *p);
+	}
+	appendStringInfoChar(out, '"');
+}
+
+/*
+ * Infix walker for the output function.  Returns the postfix index that
+ * "cur" decremented to so the caller can chain.
+ */
+static int
+infix_walk(StringInfo out, AnyQuery *q, int cur, bool top)
+{
+	AnyQueryItem *it;
+
+	check_stack_depth();
+	Assert(cur >= 0);
+	it = &q->items[cur];
+
+	if (it->type == ANYQ_VAL)
+	{
+		append_value_token(out, ANYQUERY_STRING(q, it));
+		return cur - 1;
+	}
+	else if (it->payload == ANYQ_NOT)
+	{
+		AnyQueryItem *child = &q->items[cur - 1];
+		bool		paren = (child->type == ANYQ_OPR);
+
+		appendStringInfoChar(out, '!');
+		if (paren)
+			appendStringInfoString(out, "( ");
+		cur = infix_walk(out, q, cur - 1, false);
+		if (paren)
+			appendStringInfoString(out, " )");
+		return cur;
+	}
+	else
+	{
+		int			op = it->payload;
+		StringInfoData right;
+		int			next;
+
+		if (op == ANYQ_OR && !top)
+			appendStringInfoString(out, "( ");
+
+		/* right operand first into a side buffer */
+		initStringInfo(&right);
+		next = infix_walk(&right, q, cur - 1, false);
+		/* left operand into the main buffer */
+		cur = infix_walk(out, q, next, false);
+
+		appendStringInfo(out, " %c %s", op, right.data);
+		pfree(right.data);
+
+		if (op == ANYQ_OR && !top)
+			appendStringInfoString(out, " )");
+		return cur;
+	}
+}
+
+Datum
+anyquery_out(PG_FUNCTION_ARGS)
+{
+	AnyQuery   *q = PG_GETARG_ANYQUERY_P(0);
+	StringInfoData out;
+
+	if (q->size <= 0)
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("empty anyquery")));
+
+	initStringInfo(&out);
+	(void) infix_walk(&out, q, q->size - 1, true);
+
+	PG_RETURN_CSTRING(out.data);
+}
+
+/*
+ * Debugging helper: produce a postfix string with operator codes spelled out.
+ * Mostly useful while writing tests.
+ */
+Datum
+anyquery_querytree(PG_FUNCTION_ARGS)
+{
+	AnyQuery   *q = PG_GETARG_ANYQUERY_P(0);
+	StringInfoData out;
+	int			i;
+
+	initStringInfo(&out);
+	for (i = 0; i < q->size; i++)
+	{
+		AnyQueryItem *it = &q->items[i];
+
+		if (i > 0)
+			appendStringInfoChar(&out, ' ');
+		if (it->type == ANYQ_VAL)
+			append_value_token(&out, ANYQUERY_STRING(q, it));
+		else
+			appendStringInfoChar(&out, (char) it->payload);
+	}
+	PG_RETURN_TEXT_P(cstring_to_text_with_len(out.data, out.len));
+}
+
+
+/* ------------------------------------------------------------------------
+ *  Matching: anyarray @@ anyquery
+ * ------------------------------------------------------------------------
+ */
+
+typedef struct MatchContext
+{
+	AnyArrayTypeInfo *meta;
+	Datum	   *sorted;			/* sorted array elements (owned) */
+	int			nelems;
+	/* cached parsed values for each VAL item in the query */
+	Datum	   *parsed;
+	bool	   *parsed_valid;
+} MatchContext;
+
+/*
+ * Look up val in the sorted element array via binary search.
+ */
+static bool
+contains_value(MatchContext *ctx, Datum val)
+{
+	int			lo = 0;
+	int			hi = ctx->nelems;
+
+	while (lo < hi)
+	{
+		int			mid = lo + (hi - lo) / 2;
+		int			c = DatumGetInt32(FunctionCall2Coll(&ctx->meta->cmp_proc,
+														ctx->meta->typcollation,
+														ctx->sorted[mid],
+														val));
+
+		if (c == 0)
+			return true;
+		if (c < 0)
+			lo = mid + 1;
+		else
+			hi = mid;
+	}
+	return false;
+}
+
+/*
+ * Evaluate one node of the postfix tree.  Recursive on operators.
+ */
+static bool
+eval_item(AnyQuery *q, int idx, MatchContext *ctx, Oid input_func,
+		  int input_typioparam, int32 input_typmod)
+{
+	AnyQueryItem *it;
+
+	check_stack_depth();
+	Assert(idx >= 0);
+	it = &q->items[idx];
+
+	if (it->type == ANYQ_VAL)
+	{
+		Datum		v;
+
+		if (!ctx->parsed_valid[idx])
+		{
+			const char *s = ANYQUERY_STRING(q, it);
+
+			v = OidInputFunctionCall(input_func, (char *) s,
+									 input_typioparam, input_typmod);
+			ctx->parsed[idx] = v;
+			ctx->parsed_valid[idx] = true;
+		}
+		return contains_value(ctx, ctx->parsed[idx]);
+	}
+	else if (it->payload == ANYQ_NOT)
+	{
+		return !eval_item(q, idx - 1, ctx, input_func,
+						  input_typioparam, input_typmod);
+	}
+	else if (it->payload == ANYQ_AND)
+	{
+		if (!eval_item(q, idx + it->left, ctx, input_func,
+					   input_typioparam, input_typmod))
+			return false;
+		return eval_item(q, idx - 1, ctx, input_func,
+						 input_typioparam, input_typmod);
+	}
+	else						/* ANYQ_OR */
+	{
+		if (eval_item(q, idx + it->left, ctx, input_func,
+					  input_typioparam, input_typmod))
+			return true;
+		return eval_item(q, idx - 1, ctx, input_func,
+						 input_typioparam, input_typmod);
+	}
+}
+
+static Datum
+do_boolop(FunctionCallInfo fcinfo, ArrayType *arr, AnyQuery *q)
+{
+	AnyArrayTypeInfo *meta;
+	Datum	   *values;
+	bool	   *nulls;
+	int			nelems;
+	Oid			input_func;
+	Oid			input_typioparam;
+	bool		result;
+	MatchContext ctx;
+
+	ANYARRAY_CHECK_ARRAY(arr);
+
+	if (q->size <= 0)
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("empty anyquery")));
+
+	meta = anyarray_get_meta(fcinfo, ARR_ELEMTYPE(arr), false);
+
+	if (ARR_NDIM(arr) == 0)
+	{
+		nelems = 0;
+		values = NULL;
+	}
+	else
+	{
+		deconstruct_array(arr, meta->element_type, meta->typlen,
+						  meta->typbyval, meta->typalign,
+						  &values, &nulls, &nelems);
+		pfree(nulls);
+		if (nelems > 1)
+			qsort_arg(values, nelems, sizeof(Datum),
+					  anyarray_cmp_datum, meta);
+	}
+
+	getTypeInputInfo(meta->element_type, &input_func, &input_typioparam);
+
+	ctx.meta = meta;
+	ctx.sorted = values;
+	ctx.nelems = nelems;
+	ctx.parsed = (Datum *) palloc0(sizeof(Datum) * q->size);
+	ctx.parsed_valid = (bool *) palloc0(sizeof(bool) * q->size);
+
+	result = eval_item(q, q->size - 1, &ctx, input_func,
+					   input_typioparam, -1);
+
+	pfree(ctx.parsed);
+	pfree(ctx.parsed_valid);
+	if (values)
+		pfree(values);
+
+	PG_RETURN_BOOL(result);
+}
+
+Datum
+anyarray_boolop(PG_FUNCTION_ARGS)
+{
+	ArrayType  *arr = PG_GETARG_ARRAYTYPE_P(0);
+	AnyQuery   *q = PG_GETARG_ANYQUERY_P(1);
+	Datum		result = do_boolop(fcinfo, arr, q);
+
+	PG_FREE_IF_COPY(arr, 0);
+	PG_FREE_IF_COPY(q, 1);
+	return result;
+}
+
+/*
+ * Commutator: anyquery ~~ anyarray simply swaps the arguments.
+ */
+Datum
+anyquery_boolop_rev(PG_FUNCTION_ARGS)
+{
+	AnyQuery   *q = PG_GETARG_ANYQUERY_P(0);
+	ArrayType  *arr = PG_GETARG_ARRAYTYPE_P(1);
+	Datum		result = do_boolop(fcinfo, arr, q);
+
+	PG_FREE_IF_COPY(q, 0);
+	PG_FREE_IF_COPY(arr, 1);
+	return result;
+}
diff --git a/contrib/anyarray/anyarray_gin.c b/contrib/anyarray/anyarray_gin.c
new file mode 100644
index 00000000000..d9d201c12d5
--- /dev/null
+++ b/contrib/anyarray/anyarray_gin.c
@@ -0,0 +1,374 @@
+/*-------------------------------------------------------------------------
+ *
+ * anyarray_gin.c
+ *		GIN opclasses that add the @@ (anyarray, anyquery) boolean search
+ *		operator to the existing array_ops behaviour.
+ *
+ * GIN's extractQuery support function doesn't see fn_expr, so the element
+ * type cannot be derived dynamically when the query is an anyquery (which
+ * carries only text tokens).  We work around this by exposing one opclass
+ * per concrete element type; each is a thin C wrapper that dispatches on
+ * the strategy number, delegating standard operators to inline replicas of
+ * core's array_ops behaviour and parsing anyquery tokens via the type's
+ * input function for strategy 5.
+ *
+ * Copyright (c) 2026, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *		contrib/anyarray/anyarray_gin.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "anyarray.h"
+
+#include "access/gin.h"
+#include "access/stratnum.h"
+#include "catalog/pg_type.h"
+#include "utils/array.h"
+#include "utils/builtins.h"
+#include "utils/lsyscache.h"
+
+PG_FUNCTION_INFO_V1(anyarray_gin_extract_query_int8);
+PG_FUNCTION_INFO_V1(anyarray_gin_extract_query_uuid);
+PG_FUNCTION_INFO_V1(anyarray_gin_extract_query_text);
+PG_FUNCTION_INFO_V1(anyarray_gin_consistent_int8);
+PG_FUNCTION_INFO_V1(anyarray_gin_consistent_uuid);
+PG_FUNCTION_INFO_V1(anyarray_gin_consistent_text);
+
+
+/* ------------------------------------------------------------------------
+ *  Common: extractQuery dispatcher
+ * ------------------------------------------------------------------------
+ */
+
+/*
+ * Extract array elements as GIN keys (used for strategies 1-4).
+ *
+ * Mirrors core's ginqueryarrayextract logic, but inlined so we don't depend
+ * on it being callable.  Returns a freshly-palloc'd Datum vector.
+ */
+static Datum *
+extract_array_keys(ArrayType *arr, AnyArrayTypeInfo *meta,
+				   int32 *nentries, bool **nulls_out)
+{
+	Datum	   *values;
+	bool	   *nulls;
+	int			n;
+	int			i;
+	int			j = 0;
+
+	if (ARR_NDIM(arr) == 0)
+	{
+		*nentries = 0;
+		*nulls_out = NULL;
+		return NULL;
+	}
+
+	deconstruct_array(arr, meta->element_type, meta->typlen,
+					  meta->typbyval, meta->typalign,
+					  &values, &nulls, &n);
+
+	/* compact out NULL entries (we treat NULLs as never-present) */
+	for (i = 0; i < n; i++)
+	{
+		if (!nulls[i])
+		{
+			if (j != i)
+			{
+				values[j] = values[i];
+				nulls[j] = false;
+			}
+			j++;
+		}
+	}
+
+	*nentries = j;
+	*nulls_out = nulls;
+	return values;
+}
+
+/*
+ * Walk the anyquery: every VAL is a key that must be looked up in the GIN
+ * index.  Operators (& | !) do not contribute keys.  Returns true if at
+ * least one VAL must be present for the query to possibly match (i.e. the
+ * query is not e.g. "!foo").
+ */
+static bool
+anyquery_has_required(AnyQuery *q, int idx)
+{
+	AnyQueryItem *it;
+
+	if (idx < 0)
+		return false;
+	it = &q->items[idx];
+
+	if (it->type == ANYQ_VAL)
+		return true;
+	if (it->payload == ANYQ_NOT)
+		return false;			/* assume non-required under NOT */
+	if (it->payload == ANYQ_AND)
+		return anyquery_has_required(q, idx + it->left) ||
+			anyquery_has_required(q, idx - 1);
+	/* OR: both sides must contain required values */
+	return anyquery_has_required(q, idx + it->left) &&
+		anyquery_has_required(q, idx - 1);
+}
+
+static Datum
+do_gin_extract_query(FunctionCallInfo fcinfo, Oid elem_type)
+{
+	Datum		queryDatum = PG_GETARG_DATUM(0);
+	int32	   *nentries = (int32 *) PG_GETARG_POINTER(1);
+	StrategyNumber strat = PG_GETARG_UINT16(2);
+
+	/* PG_GETARG_POINTER(3): partial_matches -- not used */
+	/* PG_GETARG_POINTER(4): extra_data -- not used */
+	bool	  **nullFlags = (bool **) PG_GETARG_POINTER(5);
+	int32	   *searchMode = (int32 *) PG_GETARG_POINTER(6);
+	Datum	   *keys = NULL;
+
+	*nentries = 0;
+	*nullFlags = NULL;
+	*searchMode = GIN_SEARCH_MODE_DEFAULT;
+
+	if (strat == ANYARRAY_GIN_BOOLEAN_STRATEGY)
+	{
+		AnyQuery   *q = DatumGetAnyQueryP(queryDatum);
+		Oid			input_func;
+		Oid			input_typioparam;
+		int			i;
+		int			k = 0;
+
+		if (q->size <= 0)
+			PG_RETURN_POINTER(NULL);
+
+		/*
+		 * If the query has no required VAL (e.g. just "!foo"), we must scan
+		 * the whole index because rows containing NONE of the queried values
+		 * are valid matches.
+		 */
+		if (!anyquery_has_required(q, q->size - 1))
+			*searchMode = GIN_SEARCH_MODE_ALL;
+
+		getTypeInputInfo(elem_type, &input_func, &input_typioparam);
+		keys = (Datum *) palloc(sizeof(Datum) * q->size);
+
+		for (i = 0; i < q->size; i++)
+		{
+			AnyQueryItem *it = &q->items[i];
+
+			if (it->type != ANYQ_VAL)
+				continue;
+			keys[k++] = OidInputFunctionCall(input_func,
+											 (char *) ANYQUERY_STRING(q, it),
+											 input_typioparam, -1);
+		}
+		*nentries = k;
+		PG_RETURN_POINTER(keys);
+	}
+	else
+	{
+		ArrayType  *arr = DatumGetArrayTypeP(queryDatum);
+		AnyArrayTypeInfo *meta = anyarray_get_meta(fcinfo, elem_type, false);
+		bool	   *nulls;
+
+		ANYARRAY_CHECK_ARRAY(arr);
+		keys = extract_array_keys(arr, meta, nentries, &nulls);
+
+		switch (strat)
+		{
+			case ANYARRAY_GIN_OVERLAP_STRATEGY:
+				*searchMode = GIN_SEARCH_MODE_DEFAULT;
+				break;
+			case ANYARRAY_GIN_CONTAINED_STRATEGY:
+				*searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY;
+				break;
+			case ANYARRAY_GIN_EQUAL_STRATEGY:
+				*searchMode = (*nentries > 0)
+					? GIN_SEARCH_MODE_DEFAULT
+					: GIN_SEARCH_MODE_INCLUDE_EMPTY;
+				break;
+			case ANYARRAY_GIN_CONTAINS_STRATEGY:
+				*searchMode = (*nentries > 0)
+					? GIN_SEARCH_MODE_DEFAULT
+					: GIN_SEARCH_MODE_ALL;
+				break;
+			default:
+				elog(ERROR, "anyarray_gin: unknown strategy number: %d", strat);
+		}
+
+		(void) nulls;			/* swallowed by extract_array_keys */
+		PG_RETURN_POINTER(keys);
+	}
+}
+
+
+/* ------------------------------------------------------------------------
+ *  Common: consistent dispatcher
+ * ------------------------------------------------------------------------
+ */
+
+/*
+ * Evaluate an anyquery against an array of "key present" flags.  The i-th
+ * VAL in postfix order corresponds to check[i] (we mapped them in
+ * extractQuery, so the j-th VAL we emitted is check[j]).  We rebuild that
+ * VAL-only mapping here as we walk the postfix tree.
+ */
+typedef struct AnyQueryCheck
+{
+	const bool *check;			/* GIN's present-key flags */
+	int			next;			/* next index in check[] */
+} AnyQueryCheck;
+
+static bool
+eval_with_check(AnyQuery *q, int idx, bool *vals)
+{
+	AnyQueryItem *it = &q->items[idx];
+
+	if (it->type == ANYQ_VAL)
+		return vals[idx];
+	if (it->payload == ANYQ_NOT)
+		return !eval_with_check(q, idx - 1, vals);
+	if (it->payload == ANYQ_AND)
+		return eval_with_check(q, idx + it->left, vals) &&
+			eval_with_check(q, idx - 1, vals);
+	/* OR */
+	return eval_with_check(q, idx + it->left, vals) ||
+		eval_with_check(q, idx - 1, vals);
+}
+
+static Datum
+do_gin_consistent(FunctionCallInfo fcinfo, Oid elem_type)
+{
+	bool	   *check = (bool *) PG_GETARG_POINTER(0);
+	StrategyNumber strat = PG_GETARG_UINT16(1);
+	Datum		queryDatum = PG_GETARG_DATUM(2);
+	int32		nkeys = PG_GETARG_INT32(3);
+
+	/* PG_GETARG_POINTER(4): extra_data -- not used */
+	bool	   *recheck = (bool *) PG_GETARG_POINTER(5);
+	bool		result = false;
+	int			i;
+
+	(void) elem_type;
+
+	if (strat == ANYARRAY_GIN_BOOLEAN_STRATEGY)
+	{
+		AnyQuery   *q = DatumGetAnyQueryP(queryDatum);
+		bool	   *vals;
+		int			k = 0;
+
+		*recheck = false;
+
+		if (q->size <= 0)
+			PG_RETURN_BOOL(false);
+
+		/* Map each VAL postfix slot to its position in check[]. */
+		vals = (bool *) palloc(sizeof(bool) * q->size);
+		for (i = 0; i < q->size; i++)
+		{
+			if (q->items[i].type == ANYQ_VAL)
+				vals[i] = check[k++];
+		}
+		result = eval_with_check(q, q->size - 1, vals);
+		pfree(vals);
+		PG_RETURN_BOOL(result);
+	}
+
+	switch (strat)
+	{
+		case ANYARRAY_GIN_OVERLAP_STRATEGY:
+			*recheck = false;
+
+			/*
+			 * GIN guarantees at least one true entry on entry; safe to say
+			 * yes
+			 */
+			for (i = 0; i < nkeys; i++)
+			{
+				if (check[i])
+				{
+					result = true;
+					break;
+				}
+			}
+			break;
+		case ANYARRAY_GIN_CONTAINED_STRATEGY:
+			*recheck = true;
+			result = true;		/* must always recheck */
+			break;
+		case ANYARRAY_GIN_EQUAL_STRATEGY:
+			*recheck = true;
+			result = true;
+			for (i = 0; i < nkeys; i++)
+			{
+				if (!check[i])
+				{
+					result = false;
+					break;
+				}
+			}
+			break;
+		case ANYARRAY_GIN_CONTAINS_STRATEGY:
+			*recheck = false;
+			result = true;
+			for (i = 0; i < nkeys; i++)
+			{
+				if (!check[i])
+				{
+					result = false;
+					break;
+				}
+			}
+			break;
+		default:
+			elog(ERROR, "anyarray_gin: unknown strategy number: %d", strat);
+	}
+
+	PG_RETURN_BOOL(result);
+}
+
+
+/* ------------------------------------------------------------------------
+ *  Per-type wrappers
+ * ------------------------------------------------------------------------
+ */
+
+Datum
+anyarray_gin_extract_query_int8(PG_FUNCTION_ARGS)
+{
+	return do_gin_extract_query(fcinfo, INT8OID);
+}
+
+Datum
+anyarray_gin_extract_query_uuid(PG_FUNCTION_ARGS)
+{
+	return do_gin_extract_query(fcinfo, UUIDOID);
+}
+
+Datum
+anyarray_gin_extract_query_text(PG_FUNCTION_ARGS)
+{
+	return do_gin_extract_query(fcinfo, TEXTOID);
+}
+
+Datum
+anyarray_gin_consistent_int8(PG_FUNCTION_ARGS)
+{
+	return do_gin_consistent(fcinfo, INT8OID);
+}
+
+Datum
+anyarray_gin_consistent_uuid(PG_FUNCTION_ARGS)
+{
+	return do_gin_consistent(fcinfo, UUIDOID);
+}
+
+Datum
+anyarray_gin_consistent_text(PG_FUNCTION_ARGS)
+{
+	return do_gin_consistent(fcinfo, TEXTOID);
+}
diff --git a/contrib/anyarray/anyarray_gist.c b/contrib/anyarray/anyarray_gist.c
new file mode 100644
index 00000000000..89570c63ded
--- /dev/null
+++ b/contrib/anyarray/anyarray_gist.c
@@ -0,0 +1,742 @@
+/*-------------------------------------------------------------------------
+ *
+ * anyarray_gist.c
+ *		Signature-based GiST opclass for anyarray.
+ *
+ * Each indexed array is summarised as a fixed-size bit vector; each element
+ * contributes a single bit chosen by its hash modulo the signature length.
+ * Internal node keys are bitwise unions of their children, with an
+ * ALLISTRUE short-circuit when every bit would be set.
+ *
+ * The opclass supports the array operators &&, @>, <@, = and the anyarray
+ * extension's @@ operator.  Because signatures are lossy, all matches are
+ * rechecked by GiST.
+ *
+ * Copyright (c) 2026, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *		contrib/anyarray/anyarray_gist.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "anyarray.h"
+
+#include "access/gist.h"
+#include "access/reloptions.h"
+#include "access/stratnum.h"
+#include "catalog/pg_index.h"
+#include "catalog/pg_type.h"
+#include "miscadmin.h"
+#include "port/pg_bitutils.h"
+#include "utils/array.h"
+#include "utils/builtins.h"
+#include "utils/lsyscache.h"
+#include "utils/rel.h"
+
+/* Strategy numbers; share R-tree conventions where applicable. */
+#define ANYARRAY_OVERLAP_STRATEGY		3
+#define ANYARRAY_CONTAINS_STRATEGY		7
+#define ANYARRAY_CONTAINED_STRATEGY		8
+#define ANYARRAY_EQUAL_STRATEGY			18
+#define ANYARRAY_BOOLEAN_STRATEGY		20
+
+PG_FUNCTION_INFO_V1(anyarray_gist_key_in);
+PG_FUNCTION_INFO_V1(anyarray_gist_key_out);
+PG_FUNCTION_INFO_V1(anyarray_gist_consistent);
+PG_FUNCTION_INFO_V1(anyarray_gist_compress);
+PG_FUNCTION_INFO_V1(anyarray_gist_decompress);
+PG_FUNCTION_INFO_V1(anyarray_gist_union);
+PG_FUNCTION_INFO_V1(anyarray_gist_same);
+PG_FUNCTION_INFO_V1(anyarray_gist_penalty);
+PG_FUNCTION_INFO_V1(anyarray_gist_picksplit);
+PG_FUNCTION_INFO_V1(anyarray_gist_options);
+
+
+/* ------------------------------------------------------------------------
+ *  Storage type stubs
+ *
+ *  The signature key is only ever constructed internally by the index AM,
+ *  so its text input/output functions reject all calls (mirroring
+ *  intbig_gkey in contrib/intarray).
+ * ------------------------------------------------------------------------
+ */
+
+Datum
+anyarray_gist_key_in(PG_FUNCTION_ARGS)
+{
+	ereport(ERROR,
+			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+			 errmsg("cannot accept a value of type %s",
+					"anyarray_gist_key")));
+	PG_RETURN_VOID();
+}
+
+Datum
+anyarray_gist_key_out(PG_FUNCTION_ARGS)
+{
+	ereport(ERROR,
+			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+			 errmsg("cannot display a value of type %s",
+					"anyarray_gist_key")));
+	PG_RETURN_VOID();
+}
+
+
+/* ------------------------------------------------------------------------
+ *  Signature helpers
+ * ------------------------------------------------------------------------
+ */
+
+static AnyArrayGistKey *
+alloc_key(bool allistrue, int siglen, const unsigned char *src)
+{
+	int32		flag = allistrue ? ANYARRAY_ALLISTRUE : 0;
+	Size		size = ANYARRAY_GKEY_SIZE(flag, siglen);
+	AnyArrayGistKey *k = (AnyArrayGistKey *) palloc(size);
+
+	SET_VARSIZE(k, size);
+	k->flag = flag;
+	if (!allistrue)
+	{
+		if (src)
+			memcpy(k->data, src, siglen);
+		else
+			memset(k->data, 0, siglen);
+	}
+	return k;
+}
+
+/*
+ * Set the bit corresponding to "val" (a btree hash value) in "sig", a bit
+ * vector of length "siglen" bytes.
+ */
+static inline void
+set_bit(unsigned char *sig, uint32 hashval, int siglen)
+{
+	uint32		bit = hashval % ((uint32) siglen * BITS_PER_BYTE);
+
+	sig[bit / BITS_PER_BYTE] |= (1U << (bit % BITS_PER_BYTE));
+}
+
+static inline bool
+get_bit(const unsigned char *sig, uint32 hashval, int siglen)
+{
+	uint32		bit = hashval % ((uint32) siglen * BITS_PER_BYTE);
+
+	return (sig[bit / BITS_PER_BYTE] >> (bit % BITS_PER_BYTE)) & 1;
+}
+
+/*
+ * Hash a single Datum of the given element type, returning an unsigned 32-bit
+ * value suitable for indexing the bit vector.
+ */
+static uint32
+hash_elem(AnyArrayTypeInfo *meta, Datum value)
+{
+	Datum		h = FunctionCall1Coll(&meta->hash_proc, meta->typcollation,
+									  value);
+
+	return (uint32) DatumGetInt32(h);
+}
+
+/*
+ * Hash each element of "arr" into "sig".  The metadata must have a valid
+ * hash_proc (use anyarray_get_meta(..., true)).
+ */
+static void
+hash_array_into(unsigned char *sig, int siglen,
+				ArrayType *arr, AnyArrayTypeInfo *meta)
+{
+	Datum	   *values;
+	bool	   *nulls;
+	int			nelems;
+	int			i;
+
+	if (ARR_NDIM(arr) == 0)
+		return;
+
+	deconstruct_array(arr, meta->element_type, meta->typlen,
+					  meta->typbyval, meta->typalign,
+					  &values, &nulls, &nelems);
+
+	for (i = 0; i < nelems; i++)
+	{
+		if (!nulls[i])
+			set_bit(sig, hash_elem(meta, values[i]), siglen);
+	}
+
+	pfree(values);
+	pfree(nulls);
+}
+
+/* Count "1" bits in a buffer of "n" bytes. */
+static int
+popcount_bytes(const unsigned char *p, int n)
+{
+	return pg_popcount((const char *) p, n);
+}
+
+
+/* ------------------------------------------------------------------------
+ *  compress / decompress
+ * ------------------------------------------------------------------------
+ */
+
+Datum
+anyarray_gist_compress(PG_FUNCTION_ARGS)
+{
+	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+	GISTENTRY  *retval = entry;
+	int			siglen = ANYARRAY_GET_SIGLEN();
+
+	if (entry->leafkey)
+	{
+		ArrayType  *arr = DatumGetArrayTypeP(entry->key);
+		AnyArrayGistKey *key;
+		AnyArrayTypeInfo *meta;
+
+		ANYARRAY_CHECK_ARRAY(arr);
+
+		meta = anyarray_get_meta(fcinfo, ARR_ELEMTYPE(arr), true);
+
+		key = alloc_key(false, siglen, NULL);
+		hash_array_into(ANYARRAY_GKEY_SIGN(key), siglen, arr, meta);
+
+		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+		gistentryinit(*retval, PointerGetDatum(key), entry->rel, entry->page,
+					  entry->offset, false);
+	}
+	else if (!ANYARRAY_GKEY_ISALLTRUE(DatumGetPointer(entry->key)))
+	{
+		AnyArrayGistKey *k = (AnyArrayGistKey *) DatumGetPointer(entry->key);
+
+		/*
+		 * If every bit happens to be set, switch to ALLISTRUE storage so
+		 * subsequent operations don't have to compare a full bit vector.
+		 */
+		if (popcount_bytes(ANYARRAY_GKEY_SIGN(k), siglen) ==
+			siglen * BITS_PER_BYTE)
+		{
+			AnyArrayGistKey *r = alloc_key(true, siglen, NULL);
+
+			retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
+			gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page,
+						  entry->offset, false);
+		}
+	}
+
+	PG_RETURN_POINTER(retval);
+}
+
+Datum
+anyarray_gist_decompress(PG_FUNCTION_ARGS)
+{
+	PG_RETURN_POINTER(PG_GETARG_POINTER(0));
+}
+
+
+/* ------------------------------------------------------------------------
+ *  union / same / penalty / picksplit / options
+ * ------------------------------------------------------------------------
+ */
+
+Datum
+anyarray_gist_union(PG_FUNCTION_ARGS)
+{
+	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
+	int		   *sizep = (int *) PG_GETARG_POINTER(1);
+	int			siglen = ANYARRAY_GET_SIGLEN();
+	AnyArrayGistKey *out;
+	unsigned char *sig;
+	int			n = entryvec->n;
+	int			i;
+	bool		all = false;
+
+	out = alloc_key(false, siglen, NULL);
+	sig = ANYARRAY_GKEY_SIGN(out);
+
+	for (i = 0; i < n; i++)
+	{
+		AnyArrayGistKey *k = (AnyArrayGistKey *)
+			DatumGetPointer(entryvec->vector[i].key);
+
+		if (ANYARRAY_GKEY_ISALLTRUE(k))
+		{
+			all = true;
+			break;
+		}
+		for (int j = 0; j < siglen; j++)
+			sig[j] |= ANYARRAY_GKEY_SIGN(k)[j];
+	}
+
+	if (all || popcount_bytes(sig, siglen) == siglen * BITS_PER_BYTE)
+	{
+		pfree(out);
+		out = alloc_key(true, siglen, NULL);
+	}
+
+	*sizep = VARSIZE(out);
+	PG_RETURN_POINTER(out);
+}
+
+Datum
+anyarray_gist_same(PG_FUNCTION_ARGS)
+{
+	AnyArrayGistKey *a = (AnyArrayGistKey *) PG_GETARG_POINTER(0);
+	AnyArrayGistKey *b = (AnyArrayGistKey *) PG_GETARG_POINTER(1);
+	bool	   *result = (bool *) PG_GETARG_POINTER(2);
+	int			siglen = ANYARRAY_GET_SIGLEN();
+
+	if (ANYARRAY_GKEY_ISALLTRUE(a) || ANYARRAY_GKEY_ISALLTRUE(b))
+		*result = ANYARRAY_GKEY_ISALLTRUE(a) && ANYARRAY_GKEY_ISALLTRUE(b);
+	else
+		*result = (memcmp(ANYARRAY_GKEY_SIGN(a), ANYARRAY_GKEY_SIGN(b),
+						  siglen) == 0);
+
+	PG_RETURN_POINTER(result);
+}
+
+/*
+ * Hamming weight of (orig OR new) - Hamming weight of orig: the number of
+ * new bits a child would introduce.  ALLISTRUE entries have the maximum
+ * possible weight (siglen*8) so the answer is 0.
+ */
+Datum
+anyarray_gist_penalty(PG_FUNCTION_ARGS)
+{
+	GISTENTRY  *origentry = (GISTENTRY *) PG_GETARG_POINTER(0);
+	GISTENTRY  *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
+	float	   *penalty = (float *) PG_GETARG_POINTER(2);
+	int			siglen = ANYARRAY_GET_SIGLEN();
+	AnyArrayGistKey *orig = (AnyArrayGistKey *) DatumGetPointer(origentry->key);
+	AnyArrayGistKey *new_ = (AnyArrayGistKey *) DatumGetPointer(newentry->key);
+
+	if (ANYARRAY_GKEY_ISALLTRUE(orig))
+	{
+		*penalty = 0.0;
+	}
+	else if (ANYARRAY_GKEY_ISALLTRUE(new_))
+	{
+		int			orig_bits = popcount_bytes(ANYARRAY_GKEY_SIGN(orig), siglen);
+
+		*penalty = (float) (siglen * BITS_PER_BYTE - orig_bits);
+	}
+	else
+	{
+		unsigned char *o = ANYARRAY_GKEY_SIGN(orig);
+		unsigned char *n = ANYARRAY_GKEY_SIGN(new_);
+		int			added = 0;
+
+		for (int i = 0; i < siglen; i++)
+		{
+			unsigned char extra = n[i] & ~o[i];
+
+			added += pg_number_of_ones[extra];
+		}
+		*penalty = (float) added;
+	}
+
+	PG_RETURN_POINTER(penalty);
+}
+
+/*
+ * Standard signature picksplit: sort entries by Hamming weight and split
+ * down the middle.  This isn't optimal but is correct and balanced; the
+ * fancier Guttman-style splits used by intbig can be added later.
+ */
+typedef struct PickSplitEntry
+{
+	OffsetNumber offset;
+	int			weight;
+} PickSplitEntry;
+
+static int
+psplit_cmp(const void *a, const void *b)
+{
+	int			wa = ((const PickSplitEntry *) a)->weight;
+	int			wb = ((const PickSplitEntry *) b)->weight;
+
+	return (wa > wb) - (wa < wb);
+}
+
+static void
+or_into(unsigned char *dst, const unsigned char *src, int siglen)
+{
+	for (int i = 0; i < siglen; i++)
+		dst[i] |= src[i];
+}
+
+Datum
+anyarray_gist_picksplit(PG_FUNCTION_ARGS)
+{
+	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
+	GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
+	int			siglen = ANYARRAY_GET_SIGLEN();
+	int			n = entryvec->n - 1;	/* entries start at index 1 */
+	PickSplitEntry *items;
+	AnyArrayGistKey *left,
+			   *right;
+	int			i;
+	int			split;
+
+	items = (PickSplitEntry *) palloc(n * sizeof(PickSplitEntry));
+	for (i = 0; i < n; i++)
+	{
+		AnyArrayGistKey *k = (AnyArrayGistKey *)
+			DatumGetPointer(entryvec->vector[i + 1].key);
+
+		items[i].offset = (OffsetNumber) (i + 1);
+		items[i].weight = ANYARRAY_GKEY_ISALLTRUE(k)
+			? siglen * BITS_PER_BYTE
+			: popcount_bytes(ANYARRAY_GKEY_SIGN(k), siglen);
+	}
+	qsort(items, n, sizeof(PickSplitEntry), psplit_cmp);
+
+	v->spl_left = (OffsetNumber *) palloc(n * sizeof(OffsetNumber));
+	v->spl_right = (OffsetNumber *) palloc(n * sizeof(OffsetNumber));
+	v->spl_nleft = 0;
+	v->spl_nright = 0;
+	left = alloc_key(false, siglen, NULL);
+	right = alloc_key(false, siglen, NULL);
+
+	split = n / 2;
+	if (split == 0)
+		split = 1;
+	if (split == n)
+		split = n - 1;
+
+	for (i = 0; i < split; i++)
+	{
+		AnyArrayGistKey *k = (AnyArrayGistKey *)
+			DatumGetPointer(entryvec->vector[items[i].offset].key);
+
+		v->spl_left[v->spl_nleft++] = items[i].offset;
+		if (ANYARRAY_GKEY_ISALLTRUE(k))
+		{
+			pfree(left);
+			left = alloc_key(true, siglen, NULL);
+		}
+		else if (!ANYARRAY_GKEY_ISALLTRUE(left))
+			or_into(ANYARRAY_GKEY_SIGN(left), ANYARRAY_GKEY_SIGN(k), siglen);
+	}
+	for (; i < n; i++)
+	{
+		AnyArrayGistKey *k = (AnyArrayGistKey *)
+			DatumGetPointer(entryvec->vector[items[i].offset].key);
+
+		v->spl_right[v->spl_nright++] = items[i].offset;
+		if (ANYARRAY_GKEY_ISALLTRUE(k))
+		{
+			pfree(right);
+			right = alloc_key(true, siglen, NULL);
+		}
+		else if (!ANYARRAY_GKEY_ISALLTRUE(right))
+			or_into(ANYARRAY_GKEY_SIGN(right), ANYARRAY_GKEY_SIGN(k), siglen);
+	}
+
+	v->spl_ldatum = PointerGetDatum(left);
+	v->spl_rdatum = PointerGetDatum(right);
+
+	pfree(items);
+	PG_RETURN_POINTER(v);
+}
+
+/* opclass options: just the signature length, in bytes */
+static void
+fill_siglen_default(int *siglen)
+{
+	*siglen = ANYARRAY_SIGLEN_DEFAULT;
+}
+
+Datum
+anyarray_gist_options(PG_FUNCTION_ARGS)
+{
+	local_relopts *relopts = (local_relopts *) PG_GETARG_POINTER(0);
+
+	init_local_reloptions(relopts, sizeof(AnyArrayGistOptions));
+	add_local_int_reloption(relopts, "siglen",
+							"signature length in bytes",
+							ANYARRAY_SIGLEN_DEFAULT, 1, ANYARRAY_SIGLEN_MAX,
+							offsetof(AnyArrayGistOptions, siglen));
+
+	(void) fill_siglen_default;
+	PG_RETURN_VOID();
+}
+
+
+/* ------------------------------------------------------------------------
+ *  consistent
+ * ------------------------------------------------------------------------
+ */
+
+/*
+ * For overlap: any single matching bit means the key MIGHT contain something
+ * the query references.  Returns true if at least one element of "query"
+ * hashes to a set bit in "sig"; ALLISTRUE keys trivially pass.
+ */
+static bool
+sig_overlap_array(const unsigned char *sig, int siglen,
+				  ArrayType *query, AnyArrayTypeInfo *meta)
+{
+	Datum	   *values;
+	bool	   *nulls;
+	int			nelems;
+	int			i;
+	bool		found = false;
+
+	if (ARR_NDIM(query) == 0)
+		return false;
+
+	deconstruct_array(query, meta->element_type, meta->typlen,
+					  meta->typbyval, meta->typalign,
+					  &values, &nulls, &nelems);
+
+	for (i = 0; i < nelems; i++)
+	{
+		if (nulls[i])
+			continue;
+		if (get_bit(sig, hash_elem(meta, values[i]), siglen))
+		{
+			found = true;
+			break;
+		}
+	}
+	pfree(values);
+	pfree(nulls);
+	return found;
+}
+
+/*
+ * For contains: every element of the query must hash to a set bit.
+ * If any required bit is missing the key cannot contain the query.
+ */
+static bool
+sig_contains_array(const unsigned char *sig, int siglen,
+				   ArrayType *query, AnyArrayTypeInfo *meta)
+{
+	Datum	   *values;
+	bool	   *nulls;
+	int			nelems;
+	int			i;
+	bool		ok = true;
+
+	if (ARR_NDIM(query) == 0)
+		return true;
+
+	deconstruct_array(query, meta->element_type, meta->typlen,
+					  meta->typbyval, meta->typalign,
+					  &values, &nulls, &nelems);
+
+	for (i = 0; i < nelems; i++)
+	{
+		if (nulls[i])
+			continue;
+		if (!get_bit(sig, hash_elem(meta, values[i]), siglen))
+		{
+			ok = false;
+			break;
+		}
+	}
+	pfree(values);
+	pfree(nulls);
+	return ok;
+}
+
+/*
+ * Recursive postfix evaluator for sig_eval_query().
+ *
+ * "vals" holds the precomputed signature lookup for every VAL slot.  NOT
+ * is non-restrictive under a signature (the bit could still be set by some
+ * other inserted array), so we conservatively report true on negation; the
+ * GiST recheck step will then filter on the real values.
+ */
+static bool
+sig_eval_walk(AnyQuery *q, int idx, const bool *vals)
+{
+	AnyQueryItem *it;
+
+	check_stack_depth();
+	Assert(idx >= 0);
+	it = &q->items[idx];
+
+	if (it->type == ANYQ_VAL)
+		return vals[idx];
+	if (it->payload == ANYQ_NOT)
+		return true;
+	if (it->payload == ANYQ_AND)
+		return sig_eval_walk(q, idx + it->left, vals) &&
+			sig_eval_walk(q, idx - 1, vals);
+	/* ANYQ_OR */
+	return sig_eval_walk(q, idx + it->left, vals) ||
+		sig_eval_walk(q, idx - 1, vals);
+}
+
+/*
+ * Evaluate an anyquery against a signature.  Each VAL is parsed using the
+ * element type's text input, hashed, then looked up in the signature.
+ */
+static bool
+sig_eval_query(const unsigned char *sig, int siglen,
+			   AnyQuery *q, AnyArrayTypeInfo *meta,
+			   Oid input_func, Oid input_typioparam)
+{
+	bool	   *vals;
+	bool		result;
+	int			i;
+
+	if (q->size <= 0)
+		return false;
+
+	vals = (bool *) palloc0(sizeof(bool) * q->size);
+
+	for (i = 0; i < q->size; i++)
+	{
+		AnyQueryItem *it = &q->items[i];
+		Datum		v;
+
+		if (it->type != ANYQ_VAL)
+			continue;
+		v = OidInputFunctionCall(input_func,
+								 (char *) ANYQUERY_STRING(q, it),
+								 input_typioparam, -1);
+		vals[i] = get_bit(sig, hash_elem(meta, v), siglen);
+	}
+
+	result = sig_eval_walk(q, q->size - 1, vals);
+	pfree(vals);
+	return result;
+}
+
+Datum
+anyarray_gist_consistent(PG_FUNCTION_ARGS)
+{
+	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+	StrategyNumber strat = (StrategyNumber) PG_GETARG_UINT16(2);
+	Oid			subtype = PG_GETARG_OID(3);
+	bool	   *recheck = (bool *) PG_GETARG_POINTER(4);
+	AnyArrayGistKey *key = (AnyArrayGistKey *) DatumGetPointer(entry->key);
+	int			siglen = ANYARRAY_GET_SIGLEN();
+	bool		result;
+
+	/* All signature-based answers require a recheck. */
+	*recheck = true;
+
+	if (ANYARRAY_GKEY_ISALLTRUE(key))
+	{
+		/* Cannot prune anything from an all-true signature. */
+		PG_RETURN_BOOL(true);
+	}
+
+	(void) subtype;
+
+	if (strat == ANYARRAY_BOOLEAN_STRATEGY)
+	{
+		AnyQuery   *q = PG_GETARG_ANYQUERY_P(1);
+		AnyArrayTypeInfo *meta;
+		Form_pg_index ind;
+		Oid			coltype;
+		Oid			elemtype;
+		Oid			input_func;
+		Oid			input_typioparam;
+
+		/*
+		 * The query is anyquery, so we recover the element type from the
+		 * indexed column's pg_index entry.  The index's own rd_att gives the
+		 * STORAGE type (anyarray_gist_key), not the original array type, so
+		 * we read the indrelid + indkey instead.
+		 */
+		ind = entry->rel->rd_index;
+		if (ind == NULL || ind->indnatts < 1)
+			ereport(ERROR,
+					(errcode(ERRCODE_INTERNAL_ERROR),
+					 errmsg("anyarray GiST index has no key column")));
+		coltype = get_atttype(ind->indrelid, ind->indkey.values[0]);
+		elemtype = get_element_type(coltype);
+		if (!OidIsValid(elemtype))
+			ereport(ERROR,
+					(errcode(ERRCODE_DATATYPE_MISMATCH),
+					 errmsg("cannot determine element type for anyquery match")));
+
+		meta = anyarray_get_meta(fcinfo, elemtype, true);
+		getTypeInputInfo(elemtype, &input_func, &input_typioparam);
+
+		result = sig_eval_query(ANYARRAY_GKEY_SIGN(key), siglen, q, meta,
+								input_func, input_typioparam);
+		PG_FREE_IF_COPY(q, 1);
+		PG_RETURN_BOOL(result);
+	}
+	else
+	{
+		ArrayType  *query = PG_GETARG_ARRAYTYPE_P(1);
+		AnyArrayTypeInfo *meta;
+
+		ANYARRAY_CHECK_ARRAY(query);
+		meta = anyarray_get_meta(fcinfo, ARR_ELEMTYPE(query), true);
+
+		switch (strat)
+		{
+			case ANYARRAY_OVERLAP_STRATEGY:
+				result = sig_overlap_array(ANYARRAY_GKEY_SIGN(key), siglen,
+										   query, meta);
+				break;
+			case ANYARRAY_CONTAINS_STRATEGY:
+				result = sig_contains_array(ANYARRAY_GKEY_SIGN(key), siglen,
+											query, meta);
+				break;
+			case ANYARRAY_CONTAINED_STRATEGY:
+
+				/*
+				 * For "key <@ query", signatures cannot exclude a non-leaf
+				 * key because its bits may come from many distinct children
+				 * which need not individually be contained in query. Always
+				 * recheck.
+				 */
+				if (GIST_LEAF(entry))
+				{
+					/*
+					 * At the leaf, every set bit must also have been set by
+					 * the query (i.e., element hashes to that bit).
+					 */
+					unsigned char *qsig;
+					int			i;
+
+					qsig = (unsigned char *) palloc0(siglen);
+					hash_array_into(qsig, siglen, query, meta);
+					result = true;
+					for (i = 0; i < siglen; i++)
+					{
+						if (ANYARRAY_GKEY_SIGN(key)[i] & ~qsig[i])
+						{
+							result = false;
+							break;
+						}
+					}
+					pfree(qsig);
+				}
+				else
+					result = true;
+				break;
+			case ANYARRAY_EQUAL_STRATEGY:
+
+				/*
+				 * The leaf signature for an equal row contains every bit of
+				 * the query's hash; internal unions contain at least those
+				 * bits.  So "key contains query bits" is a sound
+				 * over-approximation that recheck will tighten.
+				 */
+				result = sig_contains_array(ANYARRAY_GKEY_SIGN(key), siglen,
+											query, meta);
+				break;
+			default:
+				elog(ERROR, "unrecognized strategy number: %d", strat);
+				result = false;
+				break;
+		}
+
+		PG_FREE_IF_COPY(query, 1);
+		PG_RETURN_BOOL(result);
+	}
+}
diff --git a/contrib/anyarray/anyarray_op.c b/contrib/anyarray/anyarray_op.c
new file mode 100644
index 00000000000..47a050bb0e3
--- /dev/null
+++ b/contrib/anyarray/anyarray_op.c
@@ -0,0 +1,613 @@
+/*-------------------------------------------------------------------------
+ *
+ * anyarray_op.c
+ *		Set-style operations on arrays of any type.
+ *
+ * All functions accept anyarray / anyelement inputs and dispatch to the
+ * element type's btree comparison function through anyarray_get_meta().
+ * The operations mirror the corresponding intarray operations but are
+ * type-polymorphic.
+ *
+ * Copyright (c) 2026, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *		contrib/anyarray/anyarray_op.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "anyarray.h"
+
+#include "catalog/pg_type.h"
+#include "lib/qunique.h"
+#include "utils/array.h"
+#include "utils/builtins.h"
+#include "utils/lsyscache.h"
+
+
+/*
+ * deconstruct_arr_meta
+ *		Pull element values out of "arr" and fill in "*meta" for its type.
+ *
+ * Returns Datum array in *out_values (palloc'd), count in *out_nelems.  The
+ * input array must already have passed ANYARRAY_CHECK_ARRAY; we still gate
+ * on it defensively because all entry points feed through this helper.
+ */
+static void
+deconstruct_arr_meta(FunctionCallInfo fcinfo, ArrayType *arr,
+					 AnyArrayTypeInfo **out_meta,
+					 Datum **out_values, int *out_nelems)
+{
+	AnyArrayTypeInfo *meta;
+	Datum	   *values;
+	bool	   *nulls;
+	int			nelems;
+
+	ANYARRAY_CHECK_ARRAY(arr);
+
+	meta = anyarray_get_meta(fcinfo, ARR_ELEMTYPE(arr), false);
+
+	if (ARR_NDIM(arr) == 0)
+	{
+		*out_meta = meta;
+		*out_values = NULL;
+		*out_nelems = 0;
+		return;
+	}
+
+	deconstruct_array(arr, meta->element_type,
+					  meta->typlen, meta->typbyval, meta->typalign,
+					  &values, &nulls, &nelems);
+	pfree(nulls);				/* we've already rejected nulls above */
+
+	*out_meta = meta;
+	*out_values = values;
+	*out_nelems = nelems;
+}
+
+/*
+ * make_array_from_datums
+ *		Build a 1-D array from the given Datum vector.  Empty -> empty array.
+ */
+static ArrayType *
+make_array_from_datums(Datum *values, int nelems, AnyArrayTypeInfo *meta)
+{
+	if (nelems == 0)
+		return construct_empty_array(meta->element_type);
+
+	return construct_array(values, nelems, meta->element_type,
+						   meta->typlen, meta->typbyval, meta->typalign);
+}
+
+
+/* ------------------------------------------------------------------------
+ *  sort / uniq
+ * ------------------------------------------------------------------------
+ */
+
+PG_FUNCTION_INFO_V1(anyarray_sort);
+PG_FUNCTION_INFO_V1(anyarray_sort_dir);
+PG_FUNCTION_INFO_V1(anyarray_uniq);
+
+/*
+ * Sort an array ascending.
+ */
+Datum
+anyarray_sort(PG_FUNCTION_ARGS)
+{
+	ArrayType  *arr = PG_GETARG_ARRAYTYPE_P(0);
+	AnyArrayTypeInfo *meta;
+	Datum	   *values;
+	int			nelems;
+
+	deconstruct_arr_meta(fcinfo, arr, &meta, &values, &nelems);
+
+	if (nelems > 1)
+		qsort_arg(values, nelems, sizeof(Datum), anyarray_cmp_datum, meta);
+
+	PG_RETURN_ARRAYTYPE_P(make_array_from_datums(values, nelems, meta));
+}
+
+/*
+ * Sort an array.  The direction text is case-insensitive and must be one of
+ * 'asc' / 'ascending' or 'desc' / 'descending'.
+ */
+Datum
+anyarray_sort_dir(PG_FUNCTION_ARGS)
+{
+	ArrayType  *arr = PG_GETARG_ARRAYTYPE_P(0);
+	text	   *dir = PG_GETARG_TEXT_PP(1);
+	const char *dirstr = VARDATA_ANY(dir);
+	int			dirlen = VARSIZE_ANY_EXHDR(dir);
+	bool		ascending;
+	AnyArrayTypeInfo *meta;
+	Datum	   *values;
+	int			nelems;
+
+	if ((dirlen == 3 && pg_strncasecmp(dirstr, "asc", 3) == 0) ||
+		(dirlen == 9 && pg_strncasecmp(dirstr, "ascending", 9) == 0))
+		ascending = true;
+	else if ((dirlen == 4 && pg_strncasecmp(dirstr, "desc", 4) == 0) ||
+			 (dirlen == 10 && pg_strncasecmp(dirstr, "descending", 10) == 0))
+		ascending = false;
+	else
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("second parameter must be \"asc\" or \"desc\"")));
+
+	deconstruct_arr_meta(fcinfo, arr, &meta, &values, &nelems);
+
+	if (nelems > 1)
+	{
+		qsort_arg(values, nelems, sizeof(Datum), anyarray_cmp_datum, meta);
+		if (!ascending)
+		{
+			Datum	   *l = values;
+			Datum	   *r = values + nelems - 1;
+
+			while (l < r)
+			{
+				Datum		tmp = *l;
+
+				*l++ = *r;
+				*r-- = tmp;
+			}
+		}
+	}
+
+	PG_RETURN_ARRAYTYPE_P(make_array_from_datums(values, nelems, meta));
+}
+
+/*
+ * Remove duplicate elements; does not require pre-sorted input.
+ */
+Datum
+anyarray_uniq(PG_FUNCTION_ARGS)
+{
+	ArrayType  *arr = PG_GETARG_ARRAYTYPE_P(0);
+	AnyArrayTypeInfo *meta;
+	Datum	   *values;
+	int			nelems;
+	int			nunique;
+
+	deconstruct_arr_meta(fcinfo, arr, &meta, &values, &nelems);
+
+	if (nelems > 1)
+	{
+		qsort_arg(values, nelems, sizeof(Datum), anyarray_cmp_datum, meta);
+		nunique = qunique_arg(values, nelems, sizeof(Datum),
+							  anyarray_cmp_datum, meta);
+	}
+	else
+		nunique = nelems;
+
+	PG_RETURN_ARRAYTYPE_P(make_array_from_datums(values, nunique, meta));
+}
+
+
+/* ------------------------------------------------------------------------
+ *  idx / subarray / cardinality
+ * ------------------------------------------------------------------------
+ */
+
+PG_FUNCTION_INFO_V1(anyarray_idx);
+PG_FUNCTION_INFO_V1(anyarray_subarray);
+PG_FUNCTION_INFO_V1(anyarray_subarray_to_end);
+PG_FUNCTION_INFO_V1(anyarray_icount);
+
+/*
+ * Return the 1-based index of the first occurrence of "elem" in "arr",
+ * or 0 if not found.
+ */
+Datum
+anyarray_idx(PG_FUNCTION_ARGS)
+{
+	ArrayType  *arr = PG_GETARG_ARRAYTYPE_P(0);
+	Datum		elem = PG_GETARG_DATUM(1);
+	AnyArrayTypeInfo *meta;
+	Datum	   *values;
+	int			nelems;
+	int			i;
+
+	deconstruct_arr_meta(fcinfo, arr, &meta, &values, &nelems);
+
+	for (i = 0; i < nelems; i++)
+	{
+		Datum		eq = FunctionCall2Coll(&meta->eq_proc, meta->typcollation,
+										   values[i], elem);
+
+		if (DatumGetBool(eq))
+			PG_RETURN_INT32(i + 1);
+	}
+
+	PG_RETURN_INT32(0);
+}
+
+/*
+ * Common subarray extraction.  "start" is 1-based; if it is non-positive
+ * the function returns an empty array.  "len" gives the maximum number of
+ * elements to copy; if "have_len" is false the whole tail is returned.
+ */
+static ArrayType *
+do_subarray(FunctionCallInfo fcinfo, ArrayType *arr,
+			int32 start, int32 len, bool have_len)
+{
+	AnyArrayTypeInfo *meta;
+	Datum	   *values;
+	int			nelems;
+	int			off;
+	int			n;
+
+	deconstruct_arr_meta(fcinfo, arr, &meta, &values, &nelems);
+
+	if (start < 1 || start > nelems)
+		return construct_empty_array(meta->element_type);
+
+	off = start - 1;
+	if (have_len)
+	{
+		if (len <= 0)
+			return construct_empty_array(meta->element_type);
+		n = Min(len, nelems - off);
+	}
+	else
+		n = nelems - off;
+
+	return make_array_from_datums(values + off, n, meta);
+}
+
+/*
+ * subarray(arr, start, len)
+ */
+Datum
+anyarray_subarray(PG_FUNCTION_ARGS)
+{
+	ArrayType  *arr = PG_GETARG_ARRAYTYPE_P(0);
+	int32		start = PG_GETARG_INT32(1);
+	int32		len = PG_GETARG_INT32(2);
+
+	PG_RETURN_ARRAYTYPE_P(do_subarray(fcinfo, arr, start, len, true));
+}
+
+/*
+ * subarray(arr, start) -- to end
+ */
+Datum
+anyarray_subarray_to_end(PG_FUNCTION_ARGS)
+{
+	ArrayType  *arr = PG_GETARG_ARRAYTYPE_P(0);
+	int32		start = PG_GETARG_INT32(1);
+
+	PG_RETURN_ARRAYTYPE_P(do_subarray(fcinfo, arr, start, 0, false));
+}
+
+/*
+ * icount: total element count, intarray-style.  This duplicates
+ * built-in cardinality() but we expose it under the # operator the way
+ * intarray does.
+ */
+Datum
+anyarray_icount(PG_FUNCTION_ARGS)
+{
+	ArrayType  *arr = PG_GETARG_ARRAYTYPE_P(0);
+
+	ANYARRAY_CHECK_ARRAY(arr);
+	PG_RETURN_INT32(ANYARRAY_NELEMS(arr));
+}
+
+
+/* ------------------------------------------------------------------------
+ *  intersect / union / difference
+ * ------------------------------------------------------------------------
+ */
+
+PG_FUNCTION_INFO_V1(anyarray_intersect);
+PG_FUNCTION_INFO_V1(anyarray_union);
+PG_FUNCTION_INFO_V1(anyarray_union_elem);
+PG_FUNCTION_INFO_V1(anyarray_difference);
+PG_FUNCTION_INFO_V1(anyarray_difference_elem);
+
+/*
+ * deconstruct_two
+ *		Like deconstruct_arr_meta() but for two array inputs that must share
+ *		an element type.  The second array is allowed to be a different
+ *		ARRAY OID (it might come from another column) as long as the element
+ *		types match.
+ */
+static AnyArrayTypeInfo *
+deconstruct_two(FunctionCallInfo fcinfo,
+				ArrayType *a, ArrayType *b,
+				Datum **avals, int *anelems,
+				Datum **bvals, int *bnelems)
+{
+	AnyArrayTypeInfo *meta;
+	bool	   *nulls;
+
+	ANYARRAY_CHECK_ARRAY(a);
+	ANYARRAY_CHECK_ARRAY(b);
+
+	if (ARR_ELEMTYPE(a) != ARR_ELEMTYPE(b))
+		ereport(ERROR,
+				(errcode(ERRCODE_DATATYPE_MISMATCH),
+				 errmsg("cannot operate on arrays of different element types"),
+				 errdetail("Left operand has element type %s, right operand has %s.",
+						   format_type_be(ARR_ELEMTYPE(a)),
+						   format_type_be(ARR_ELEMTYPE(b)))));
+
+	meta = anyarray_get_meta(fcinfo, ARR_ELEMTYPE(a), false);
+
+	if (ARR_NDIM(a) == 0)
+	{
+		*avals = NULL;
+		*anelems = 0;
+	}
+	else
+	{
+		deconstruct_array(a, meta->element_type, meta->typlen,
+						  meta->typbyval, meta->typalign,
+						  avals, &nulls, anelems);
+		pfree(nulls);
+	}
+
+	if (ARR_NDIM(b) == 0)
+	{
+		*bvals = NULL;
+		*bnelems = 0;
+	}
+	else
+	{
+		deconstruct_array(b, meta->element_type, meta->typlen,
+						  meta->typbyval, meta->typalign,
+						  bvals, &nulls, bnelems);
+		pfree(nulls);
+	}
+
+	return meta;
+}
+
+/*
+ * Sort + de-dup in place.  Returns the new length.
+ */
+static int
+sort_uniq(Datum *values, int nelems, AnyArrayTypeInfo *meta)
+{
+	if (nelems <= 1)
+		return nelems;
+
+	qsort_arg(values, nelems, sizeof(Datum), anyarray_cmp_datum, meta);
+	return qunique_arg(values, nelems, sizeof(Datum),
+					   anyarray_cmp_datum, meta);
+}
+
+/*
+ * Intersection: returns the sorted, deduplicated values present in both
+ * inputs.
+ */
+Datum
+anyarray_intersect(PG_FUNCTION_ARGS)
+{
+	ArrayType  *a = PG_GETARG_ARRAYTYPE_P(0);
+	ArrayType  *b = PG_GETARG_ARRAYTYPE_P(1);
+	AnyArrayTypeInfo *meta;
+	Datum	   *av,
+			   *bv,
+			   *out;
+	int			an,
+				bn,
+				i = 0,
+				j = 0,
+				k = 0;
+
+	meta = deconstruct_two(fcinfo, a, b, &av, &an, &bv, &bn);
+
+	an = sort_uniq(av, an, meta);
+	bn = sort_uniq(bv, bn, meta);
+
+	out = (Datum *) palloc(sizeof(Datum) * Min(an, bn));
+	while (i < an && j < bn)
+	{
+		int			cmp = anyarray_cmp_datum(&av[i], &bv[j], meta);
+
+		if (cmp == 0)
+		{
+			out[k++] = av[i];
+			i++;
+			j++;
+		}
+		else if (cmp < 0)
+			i++;
+		else
+			j++;
+	}
+
+	PG_RETURN_ARRAYTYPE_P(make_array_from_datums(out, k, meta));
+}
+
+/*
+ * Union: returns the sorted, deduplicated values present in either input.
+ */
+Datum
+anyarray_union(PG_FUNCTION_ARGS)
+{
+	ArrayType  *a = PG_GETARG_ARRAYTYPE_P(0);
+	ArrayType  *b = PG_GETARG_ARRAYTYPE_P(1);
+	AnyArrayTypeInfo *meta;
+	Datum	   *av,
+			   *bv,
+			   *out;
+	int			an,
+				bn,
+				i = 0,
+				j = 0,
+				k = 0;
+
+	meta = deconstruct_two(fcinfo, a, b, &av, &an, &bv, &bn);
+
+	an = sort_uniq(av, an, meta);
+	bn = sort_uniq(bv, bn, meta);
+
+	out = (Datum *) palloc(sizeof(Datum) * (an + bn));
+	while (i < an && j < bn)
+	{
+		int			cmp = anyarray_cmp_datum(&av[i], &bv[j], meta);
+
+		if (cmp == 0)
+		{
+			out[k++] = av[i];
+			i++;
+			j++;
+		}
+		else if (cmp < 0)
+			out[k++] = av[i++];
+		else
+			out[k++] = bv[j++];
+	}
+	while (i < an)
+		out[k++] = av[i++];
+	while (j < bn)
+		out[k++] = bv[j++];
+
+	PG_RETURN_ARRAYTYPE_P(make_array_from_datums(out, k, meta));
+}
+
+/*
+ * array | element : add element if not already present, returning the
+ * sorted, deduplicated result.
+ */
+Datum
+anyarray_union_elem(PG_FUNCTION_ARGS)
+{
+	ArrayType  *a = PG_GETARG_ARRAYTYPE_P(0);
+	Datum		elem = PG_GETARG_DATUM(1);
+	Oid			elem_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
+	AnyArrayTypeInfo *meta;
+	Datum	   *values;
+	int			nelems;
+	int			out_n;
+
+	ANYARRAY_CHECK_ARRAY(a);
+
+	if (ARR_ELEMTYPE(a) != elem_type)
+		ereport(ERROR,
+				(errcode(ERRCODE_DATATYPE_MISMATCH),
+				 errmsg("element type does not match array element type")));
+
+	meta = anyarray_get_meta(fcinfo, ARR_ELEMTYPE(a), false);
+
+	if (ARR_NDIM(a) == 0)
+	{
+		nelems = 0;
+		values = (Datum *) palloc(sizeof(Datum));
+	}
+	else
+	{
+		bool	   *nulls;
+
+		deconstruct_array(a, meta->element_type, meta->typlen,
+						  meta->typbyval, meta->typalign,
+						  &values, &nulls, &nelems);
+		pfree(nulls);
+		values = repalloc(values, sizeof(Datum) * (nelems + 1));
+	}
+
+	values[nelems++] = elem;
+
+	out_n = sort_uniq(values, nelems, meta);
+	PG_RETURN_ARRAYTYPE_P(make_array_from_datums(values, out_n, meta));
+}
+
+/*
+ * Difference: returns sorted, deduplicated values from "a" that are not in
+ * "b".
+ */
+Datum
+anyarray_difference(PG_FUNCTION_ARGS)
+{
+	ArrayType  *a = PG_GETARG_ARRAYTYPE_P(0);
+	ArrayType  *b = PG_GETARG_ARRAYTYPE_P(1);
+	AnyArrayTypeInfo *meta;
+	Datum	   *av,
+			   *bv,
+			   *out;
+	int			an,
+				bn,
+				i = 0,
+				j = 0,
+				k = 0;
+
+	meta = deconstruct_two(fcinfo, a, b, &av, &an, &bv, &bn);
+
+	an = sort_uniq(av, an, meta);
+	bn = sort_uniq(bv, bn, meta);
+
+	out = (Datum *) palloc(sizeof(Datum) * an);
+	while (i < an && j < bn)
+	{
+		int			cmp = anyarray_cmp_datum(&av[i], &bv[j], meta);
+
+		if (cmp == 0)
+		{
+			i++;
+			j++;
+		}
+		else if (cmp < 0)
+			out[k++] = av[i++];
+		else
+			j++;
+	}
+	while (i < an)
+		out[k++] = av[i++];
+
+	PG_RETURN_ARRAYTYPE_P(make_array_from_datums(out, k, meta));
+}
+
+/*
+ * array - element : remove all occurrences of "elem", preserving order.
+ * (Note: intarray returns the input order-preserved; we do the same.)
+ */
+Datum
+anyarray_difference_elem(PG_FUNCTION_ARGS)
+{
+	ArrayType  *a = PG_GETARG_ARRAYTYPE_P(0);
+	Datum		elem = PG_GETARG_DATUM(1);
+	Oid			elem_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
+	AnyArrayTypeInfo *meta;
+	Datum	   *values;
+	int			nelems;
+	int			i,
+				k = 0;
+
+	ANYARRAY_CHECK_ARRAY(a);
+
+	if (ARR_ELEMTYPE(a) != elem_type)
+		ereport(ERROR,
+				(errcode(ERRCODE_DATATYPE_MISMATCH),
+				 errmsg("element type does not match array element type")));
+
+	meta = anyarray_get_meta(fcinfo, ARR_ELEMTYPE(a), false);
+
+	if (ARR_NDIM(a) == 0)
+		PG_RETURN_ARRAYTYPE_P(construct_empty_array(meta->element_type));
+
+	{
+		bool	   *nulls;
+
+		deconstruct_array(a, meta->element_type, meta->typlen,
+						  meta->typbyval, meta->typalign,
+						  &values, &nulls, &nelems);
+		pfree(nulls);
+	}
+
+	for (i = 0; i < nelems; i++)
+	{
+		Datum		eq = FunctionCall2Coll(&meta->eq_proc, meta->typcollation,
+										   values[i], elem);
+
+		if (!DatumGetBool(eq))
+			values[k++] = values[i];
+	}
+
+	PG_RETURN_ARRAYTYPE_P(make_array_from_datums(values, k, meta));
+}
diff --git a/contrib/anyarray/expected/anyarray.out b/contrib/anyarray/expected/anyarray.out
new file mode 100644
index 00000000000..b17c6ef033e
--- /dev/null
+++ b/contrib/anyarray/expected/anyarray.out
@@ -0,0 +1,727 @@
+CREATE EXTENSION anyarray;
+--
+-- Phase 1: set operations, helpers and operators for int8, uuid, text
+--
+-- ===== int8 =====
+SELECT anyarray_sort(ARRAY[3, 1, 2, 1]::int8[]);
+ anyarray_sort 
+---------------
+ {1,1,2,3}
+(1 row)
+
+SELECT anyarray_sort(ARRAY[3, 1, 2, 1]::int8[], 'desc');
+ anyarray_sort 
+---------------
+ {3,2,1,1}
+(1 row)
+
+SELECT anyarray_sort(ARRAY[]::int8[]);
+ anyarray_sort 
+---------------
+ {}
+(1 row)
+
+SELECT anyarray_uniq(ARRAY[1, 1, 2, 3, 3, 2]::int8[]);
+ anyarray_uniq 
+---------------
+ {1,2,3}
+(1 row)
+
+SELECT anyarray_idx(ARRAY[10, 20, 30]::int8[], 20::int8);
+ anyarray_idx 
+--------------
+            2
+(1 row)
+
+SELECT anyarray_idx(ARRAY[10, 20, 30]::int8[], 99::int8);
+ anyarray_idx 
+--------------
+            0
+(1 row)
+
+SELECT anyarray_subarray(ARRAY[1,2,3,4,5]::int8[], 2, 2);
+ anyarray_subarray 
+-------------------
+ {2,3}
+(1 row)
+
+SELECT anyarray_subarray(ARRAY[1,2,3,4,5]::int8[], 3);
+ anyarray_subarray 
+-------------------
+ {3,4,5}
+(1 row)
+
+SELECT anyarray_subarray(ARRAY[1,2,3]::int8[], 5, 1);
+ anyarray_subarray 
+-------------------
+ {}
+(1 row)
+
+SELECT ARRAY[1,2,3]::int8[] & ARRAY[2,3,4]::int8[];
+ ?column? 
+----------
+ {2,3}
+(1 row)
+
+SELECT ARRAY[1,2,3]::int8[] | ARRAY[3,4,5]::int8[];
+  ?column?   
+-------------
+ {1,2,3,4,5}
+(1 row)
+
+SELECT ARRAY[1,2,3]::int8[] | 4::int8;
+ ?column?  
+-----------
+ {1,2,3,4}
+(1 row)
+
+SELECT ARRAY[1,2,3,4]::int8[] - ARRAY[2,4]::int8[];
+ ?column? 
+----------
+ {1,3}
+(1 row)
+
+SELECT ARRAY[1,2,2,3,2]::int8[] - 2::int8;
+ ?column? 
+----------
+ {1,3}
+(1 row)
+
+SELECT # ARRAY[10,20,30]::int8[];
+ ?column? 
+----------
+        3
+(1 row)
+
+SELECT ARRAY[10,20,30]::int8[] # 20::int8;
+ ?column? 
+----------
+        2
+(1 row)
+
+-- ===== uuid =====
+SELECT anyarray_sort(ARRAY[
+  '00000000-0000-0000-0000-000000000003'::uuid,
+  '00000000-0000-0000-0000-000000000001',
+  '00000000-0000-0000-0000-000000000002']);
+                                                  anyarray_sort                                                   
+------------------------------------------------------------------------------------------------------------------
+ {00000000-0000-0000-0000-000000000001,00000000-0000-0000-0000-000000000002,00000000-0000-0000-0000-000000000003}
+(1 row)
+
+SELECT anyarray_uniq(ARRAY[
+  '00000000-0000-0000-0000-000000000001'::uuid,
+  '00000000-0000-0000-0000-000000000001',
+  '00000000-0000-0000-0000-000000000002']);
+                                anyarray_uniq                                
+-----------------------------------------------------------------------------
+ {00000000-0000-0000-0000-000000000001,00000000-0000-0000-0000-000000000002}
+(1 row)
+
+SELECT anyarray_idx(ARRAY[
+  '00000000-0000-0000-0000-000000000001'::uuid,
+  '00000000-0000-0000-0000-000000000002'],
+  '00000000-0000-0000-0000-000000000002'::uuid);
+ anyarray_idx 
+--------------
+            2
+(1 row)
+
+SELECT ARRAY['00000000-0000-0000-0000-000000000001'::uuid,
+             '00000000-0000-0000-0000-000000000002']
+     & ARRAY['00000000-0000-0000-0000-000000000002'::uuid,
+             '00000000-0000-0000-0000-000000000003'];
+                ?column?                
+----------------------------------------
+ {00000000-0000-0000-0000-000000000002}
+(1 row)
+
+SELECT ARRAY['00000000-0000-0000-0000-000000000001'::uuid]
+     | '00000000-0000-0000-0000-000000000002'::uuid;
+                                  ?column?                                   
+-----------------------------------------------------------------------------
+ {00000000-0000-0000-0000-000000000001,00000000-0000-0000-0000-000000000002}
+(1 row)
+
+-- ===== text =====
+SELECT anyarray_sort(ARRAY['banana','apple','cherry']);
+     anyarray_sort     
+-----------------------
+ {apple,banana,cherry}
+(1 row)
+
+SELECT anyarray_sort(ARRAY['banana','apple','cherry'], 'desc');
+     anyarray_sort     
+-----------------------
+ {cherry,banana,apple}
+(1 row)
+
+SELECT anyarray_uniq(ARRAY['a','b','a','c','b']);
+ anyarray_uniq 
+---------------
+ {a,b,c}
+(1 row)
+
+SELECT anyarray_idx(ARRAY['a','b','c'], 'b'::text);
+ anyarray_idx 
+--------------
+            2
+(1 row)
+
+SELECT ARRAY['a','b','c']::text[] & ARRAY['b','c','d']::text[];
+ ?column? 
+----------
+ {b,c}
+(1 row)
+
+SELECT ARRAY['a','b','c']::text[] | 'd'::text;
+ ?column?  
+-----------
+ {a,b,c,d}
+(1 row)
+
+SELECT ARRAY['a','b','c','b']::text[] - 'b'::text;
+ ?column? 
+----------
+ {a,c}
+(1 row)
+
+-- ===== error cases =====
+-- multi-dim
+SELECT anyarray_sort(ARRAY[[1,2],[3,4]]::int8[]);
+ERROR:  multidimensional arrays are not supported
+-- nulls
+SELECT anyarray_sort(ARRAY[1, NULL, 2]::int8[]);
+ERROR:  array must not contain nulls
+-- bad direction
+SELECT anyarray_sort(ARRAY[1,2,3]::int8[], 'bogus');
+ERROR:  second parameter must be "asc" or "desc"
+--
+-- Phase 2: anyquery and @@ operator
+--
+-- parsing + output round-trip
+SELECT '1 & 2'::anyquery::text;
+ text  
+-------
+ 1 & 2
+(1 row)
+
+SELECT '1 & 2 | 3'::anyquery::text;
+   text    
+-----------
+ 1 & 2 | 3
+(1 row)
+
+SELECT '(1 | 2) & 3'::anyquery::text;
+     text      
+---------------
+ ( 1 | 2 ) & 3
+(1 row)
+
+SELECT '!1 & 2'::anyquery::text;
+  text  
+--------
+ !1 & 2
+(1 row)
+
+SELECT '!(1 | 2) & 3'::anyquery::text;
+        text        
+--------------------
+ !( ( 1 | 2 ) ) & 3
+(1 row)
+
+SELECT '"hello world" | foo'::anyquery::text;
+        text         
+---------------------
+ "hello world" | foo
+(1 row)
+
+SELECT anyquery_querytree('1 & 2 | 3'::anyquery);
+ anyquery_querytree 
+--------------------
+ 1 2 & 3 |
+(1 row)
+
+-- int8 matching
+SELECT ARRAY[1,2,3]::int8[] @@ '1'::anyquery;
+ ?column? 
+----------
+ t
+(1 row)
+
+SELECT ARRAY[1,2,3]::int8[] @@ '1 & 2'::anyquery;
+ ?column? 
+----------
+ t
+(1 row)
+
+SELECT ARRAY[1,2,3]::int8[] @@ '1 & 4'::anyquery;
+ ?column? 
+----------
+ f
+(1 row)
+
+SELECT ARRAY[1,2,3]::int8[] @@ '1 | 4'::anyquery;
+ ?column? 
+----------
+ t
+(1 row)
+
+SELECT ARRAY[1,2,3]::int8[] @@ '!4'::anyquery;
+ ?column? 
+----------
+ t
+(1 row)
+
+SELECT ARRAY[1,2,3]::int8[] @@ '!1'::anyquery;
+ ?column? 
+----------
+ f
+(1 row)
+
+SELECT ARRAY[1,2,3]::int8[] @@ '!4 & 1'::anyquery;
+ ?column? 
+----------
+ t
+(1 row)
+
+SELECT ARRAY[1,2,3]::int8[] @@ '(1 | 4) & (2 | 5)'::anyquery;
+ ?column? 
+----------
+ t
+(1 row)
+
+-- commutator
+SELECT '1 & 2'::anyquery ~~ ARRAY[1,2,3]::int8[];
+ ?column? 
+----------
+ t
+(1 row)
+
+SELECT '1 & 4'::anyquery ~~ ARRAY[1,2,3]::int8[];
+ ?column? 
+----------
+ f
+(1 row)
+
+-- uuid
+SELECT ARRAY['00000000-0000-0000-0000-000000000001'::uuid,
+             '00000000-0000-0000-0000-000000000002']
+       @@ '00000000-0000-0000-0000-000000000001 & 00000000-0000-0000-0000-000000000002'::anyquery;
+ ?column? 
+----------
+ t
+(1 row)
+
+SELECT ARRAY['00000000-0000-0000-0000-000000000001'::uuid]
+       @@ '00000000-0000-0000-0000-000000000002'::anyquery;
+ ?column? 
+----------
+ f
+(1 row)
+
+-- text
+SELECT ARRAY['apple','banana','cherry']::text[] @@ 'apple & banana'::anyquery;
+ ?column? 
+----------
+ t
+(1 row)
+
+SELECT ARRAY['apple','banana','cherry']::text[] @@ '"banana" | grape'::anyquery;
+ ?column? 
+----------
+ t
+(1 row)
+
+SELECT ARRAY['apple','banana','cherry']::text[] @@ 'durian | grape'::anyquery;
+ ?column? 
+----------
+ f
+(1 row)
+
+-- empty array
+SELECT ARRAY[]::int8[] @@ '1'::anyquery;
+ ?column? 
+----------
+ f
+(1 row)
+
+SELECT ARRAY[]::int8[] @@ '!1'::anyquery;
+ ?column? 
+----------
+ t
+(1 row)
+
+-- parse errors
+SELECT ''::anyquery;
+ERROR:  unexpected end of input in anyquery
+LINE 1: SELECT ''::anyquery;
+               ^
+SELECT '1 &'::anyquery;
+ERROR:  unexpected end of input in anyquery
+LINE 1: SELECT '1 &'::anyquery;
+               ^
+SELECT '1 & (2'::anyquery;
+ERROR:  missing closing parenthesis in anyquery
+LINE 1: SELECT '1 & (2'::anyquery;
+               ^
+SELECT '1 ) 2'::anyquery;
+ERROR:  unexpected trailing input in anyquery
+LINE 1: SELECT '1 ) 2'::anyquery;
+               ^
+-- runtime errors: token cannot be parsed as element type
+SELECT ARRAY[1,2]::int8[] @@ 'abc'::anyquery;
+ERROR:  invalid input syntax for type bigint: "abc"
+--
+-- Phase 3: GiST signature index
+--
+-- amvalidate: well-formed opclass
+SELECT amname, opcname FROM pg_opclass opc
+LEFT JOIN pg_am am ON am.oid = opcmethod
+WHERE opc.opcname = 'anyarray_gist_ops' AND NOT amvalidate(opc.oid);
+ amname | opcname 
+--------+---------
+(0 rows)
+
+-- int8 GiST: build deterministic table
+CREATE TABLE anyarray_gist_int8 (id int, a int8[]);
+INSERT INTO anyarray_gist_int8 VALUES
+  (1, ARRAY[1,2,3]::int8[]),
+  (2, ARRAY[10,20,30]::int8[]),
+  (3, ARRAY[10,20,30]::int8[]),
+  (4, ARRAY[1,2,3,4,5]::int8[]),
+  (5, ARRAY[100,200]::int8[]);
+CREATE INDEX anyarray_gist_int8_idx
+  ON anyarray_gist_int8 USING gist(a anyarray_gist_ops);
+SET enable_seqscan = off;
+SELECT id FROM anyarray_gist_int8 WHERE a @> ARRAY[1,2]::int8[] ORDER BY id;
+ id 
+----
+  1
+  4
+(2 rows)
+
+SELECT id FROM anyarray_gist_int8 WHERE a && ARRAY[10,200]::int8[] ORDER BY id;
+ id 
+----
+  2
+  3
+  5
+(3 rows)
+
+SELECT id FROM anyarray_gist_int8 WHERE a = ARRAY[10,20,30]::int8[] ORDER BY id;
+ id 
+----
+  2
+  3
+(2 rows)
+
+SELECT id FROM anyarray_gist_int8 WHERE a <@ ARRAY[1,2,3,4,5]::int8[] ORDER BY id;
+ id 
+----
+  1
+  4
+(2 rows)
+
+SELECT id FROM anyarray_gist_int8 WHERE a @@ '10 & 20'::anyquery ORDER BY id;
+ id 
+----
+  2
+  3
+(2 rows)
+
+SELECT id FROM anyarray_gist_int8 WHERE a @@ '1 | 100'::anyquery ORDER BY id;
+ id 
+----
+  1
+  4
+  5
+(3 rows)
+
+SELECT id FROM anyarray_gist_int8 WHERE a @@ '!1 & 10'::anyquery ORDER BY id;
+ id 
+----
+  2
+  3
+(2 rows)
+
+-- result consistency: GiST must agree with seqscan
+SELECT (
+  SELECT count(*) FROM anyarray_gist_int8 WHERE a @> ARRAY[10]::int8[]
+) = (
+  SELECT count(*) FROM (SELECT 1 FROM anyarray_gist_int8 WHERE a @> ARRAY[10]::int8[]) s
+) AS gist_matches_seqscan;
+ gist_matches_seqscan 
+----------------------
+ t
+(1 row)
+
+RESET enable_seqscan;
+-- text GiST
+CREATE TABLE anyarray_gist_text (id int, a text[]);
+INSERT INTO anyarray_gist_text VALUES
+  (1, ARRAY['apple','banana']),
+  (2, ARRAY['banana','cherry']),
+  (3, ARRAY['apple','cherry','durian']);
+CREATE INDEX anyarray_gist_text_idx
+  ON anyarray_gist_text USING gist(a anyarray_gist_ops(siglen=64));
+SET enable_seqscan = off;
+SELECT id FROM anyarray_gist_text WHERE a @> ARRAY['apple']::text[] ORDER BY id;
+ id 
+----
+  1
+  3
+(2 rows)
+
+SELECT id FROM anyarray_gist_text WHERE a @@ 'apple & cherry'::anyquery ORDER BY id;
+ id 
+----
+  3
+(1 row)
+
+RESET enable_seqscan;
+-- siglen bounds
+CREATE INDEX ON anyarray_gist_text USING gist(a anyarray_gist_ops(siglen=0));
+ERROR:  value 0 out of bounds for option "siglen"
+DETAIL:  Valid values are between "1" and "2024".
+CREATE INDEX ON anyarray_gist_text USING gist(a anyarray_gist_ops(siglen=8193));
+ERROR:  value 8193 out of bounds for option "siglen"
+DETAIL:  Valid values are between "1" and "2024".
+--
+-- Phase 4: GIN index (per-type, supports standard ops + @@)
+--
+-- amvalidate: all three opclasses
+SELECT amname, opcname FROM pg_opclass opc
+LEFT JOIN pg_am am ON am.oid = opcmethod
+WHERE opc.opcname LIKE '%anyquery_gin_ops' AND NOT amvalidate(opc.oid);
+ amname | opcname 
+--------+---------
+(0 rows)
+
+-- int8 GIN
+CREATE TABLE anyarray_gin_int8 (id int, a int8[]);
+INSERT INTO anyarray_gin_int8 VALUES
+  (1, ARRAY[1,2,3]::int8[]),
+  (2, ARRAY[10,20,30]::int8[]),
+  (3, ARRAY[10,20,30]::int8[]),
+  (4, ARRAY[1,2,3,4,5]::int8[]),
+  (5, ARRAY[100,200]::int8[]);
+CREATE INDEX anyarray_gin_int8_idx
+  ON anyarray_gin_int8 USING gin(a int8_anyquery_gin_ops);
+SET enable_seqscan = off;
+SELECT id FROM anyarray_gin_int8 WHERE a @> ARRAY[1,2]::int8[] ORDER BY id;
+ id 
+----
+  1
+  4
+(2 rows)
+
+SELECT id FROM anyarray_gin_int8 WHERE a && ARRAY[10,200]::int8[] ORDER BY id;
+ id 
+----
+  2
+  3
+  5
+(3 rows)
+
+SELECT id FROM anyarray_gin_int8 WHERE a @@ '10 & 20'::anyquery ORDER BY id;
+ id 
+----
+  2
+  3
+(2 rows)
+
+SELECT id FROM anyarray_gin_int8 WHERE a @@ '(1 & 2) | 100'::anyquery ORDER BY id;
+ id 
+----
+  1
+  4
+  5
+(3 rows)
+
+SELECT id FROM anyarray_gin_int8 WHERE a @@ '!1'::anyquery ORDER BY id;
+ id 
+----
+  2
+  3
+  5
+(3 rows)
+
+-- uuid GIN
+CREATE TABLE anyarray_gin_uuid (id int, a uuid[]);
+INSERT INTO anyarray_gin_uuid VALUES
+  (1, ARRAY['11111111-1111-1111-1111-111111111111'::uuid,
+            '22222222-2222-2222-2222-222222222222']),
+  (2, ARRAY['33333333-3333-3333-3333-333333333333'::uuid]),
+  (3, ARRAY['11111111-1111-1111-1111-111111111111'::uuid,
+            '33333333-3333-3333-3333-333333333333']);
+CREATE INDEX anyarray_gin_uuid_idx
+  ON anyarray_gin_uuid USING gin(a uuid_anyquery_gin_ops);
+SET enable_seqscan = off;
+SELECT id FROM anyarray_gin_uuid
+  WHERE a @@ '11111111-1111-1111-1111-111111111111 & 22222222-2222-2222-2222-222222222222'::anyquery
+  ORDER BY id;
+ id 
+----
+  1
+(1 row)
+
+SELECT id FROM anyarray_gin_uuid
+  WHERE a @> ARRAY['11111111-1111-1111-1111-111111111111'::uuid]
+  ORDER BY id;
+ id 
+----
+  1
+  3
+(2 rows)
+
+RESET enable_seqscan;
+-- text GIN
+CREATE TABLE anyarray_gin_text (id int, a text[]);
+INSERT INTO anyarray_gin_text VALUES
+  (1, ARRAY['apple','banana']),
+  (2, ARRAY['banana','cherry']),
+  (3, ARRAY['apple','cherry','durian']);
+CREATE INDEX anyarray_gin_text_idx
+  ON anyarray_gin_text USING gin(a text_anyquery_gin_ops);
+SET enable_seqscan = off;
+SELECT id FROM anyarray_gin_text WHERE a @@ 'apple & cherry'::anyquery ORDER BY id;
+ id 
+----
+  3
+(1 row)
+
+SELECT id FROM anyarray_gin_text WHERE a @@ '"durian"'::anyquery ORDER BY id;
+ id 
+----
+  3
+(1 row)
+
+SELECT id FROM anyarray_gin_text WHERE a @@ 'apple | grape'::anyquery ORDER BY id;
+ id 
+----
+  1
+  3
+(2 rows)
+
+SELECT id FROM anyarray_gin_text WHERE a @@ '!banana'::anyquery ORDER BY id;
+ id 
+----
+  3
+(1 row)
+
+RESET enable_seqscan;
+--
+-- Phase 5: cross-AM consistency and edge cases
+--
+-- Build a larger deterministic int8 table and index it with both GiST and
+-- GIN.  Then run each candidate query under seqscan, GiST and GIN and check
+-- that all three plans return the same row set.
+--
+CREATE TABLE anyarray_xcheck (id int, a int8[]);
+INSERT INTO anyarray_xcheck
+SELECT g,
+       ARRAY[(g % 7)::int8, ((g * 3) % 11)::int8, ((g + 1) % 5)::int8]
+FROM generate_series(1, 200) g;
+-- a few hand-picked rows to exercise common values
+INSERT INTO anyarray_xcheck VALUES
+  (1001, ARRAY[1,2,3,4,5]::int8[]),
+  (1002, ARRAY[1,2,3,4,5]::int8[]),
+  (1003, ARRAY[100,200,300]::int8[]),
+  (1004, ARRAY[]::int8[]),
+  (1005, NULL);
+CREATE INDEX anyarray_xcheck_gist ON anyarray_xcheck
+  USING gist(a anyarray_gist_ops);
+CREATE INDEX anyarray_xcheck_gin ON anyarray_xcheck
+  USING gin(a int8_anyquery_gin_ops);
+-- Run each predicate three times: pure seqscan, GiST-only, GIN-only.
+-- All three result sets must match.
+CREATE FUNCTION anyarray_xcheck_match(pred text)
+RETURNS TABLE(gist_ok bool, gin_ok bool)
+LANGUAGE plpgsql AS $$
+DECLARE
+  seq int[]; gst int[]; gin int[];
+BEGIN
+  SET LOCAL enable_seqscan = on;
+  SET LOCAL enable_indexscan = off;
+  SET LOCAL enable_bitmapscan = off;
+  EXECUTE 'SELECT array_agg(id ORDER BY id) FROM anyarray_xcheck WHERE '
+          || pred INTO seq;
+
+  -- Force GiST by hiding the GIN index.
+  ALTER INDEX anyarray_xcheck_gin SET (fastupdate = off);
+  SET LOCAL enable_seqscan = off;
+  SET LOCAL enable_indexscan = on;
+  SET LOCAL enable_bitmapscan = on;
+  DROP INDEX anyarray_xcheck_gin;
+  EXECUTE 'SELECT array_agg(id ORDER BY id) FROM anyarray_xcheck WHERE '
+          || pred INTO gst;
+  CREATE INDEX anyarray_xcheck_gin ON anyarray_xcheck
+    USING gin(a int8_anyquery_gin_ops);
+
+  -- Force GIN by hiding GiST.
+  DROP INDEX anyarray_xcheck_gist;
+  EXECUTE 'SELECT array_agg(id ORDER BY id) FROM anyarray_xcheck WHERE '
+          || pred INTO gin;
+  CREATE INDEX anyarray_xcheck_gist ON anyarray_xcheck
+    USING gist(a anyarray_gist_ops);
+
+  gist_ok := seq IS NOT DISTINCT FROM gst;
+  gin_ok  := seq IS NOT DISTINCT FROM gin;
+  RETURN NEXT;
+END $$;
+SELECT pred, gist_ok, gin_ok FROM (VALUES
+  ('a @> ARRAY[1,2]::int8[]'),
+  ('a @> ARRAY[100,200]::int8[]'),
+  ('a && ARRAY[5,99]::int8[]'),
+  ('a = ARRAY[1,2,3,4,5]::int8[]'),
+  ('a @@ ''1 & 2''::anyquery'),
+  ('a @@ ''100 | 999''::anyquery'),
+  ('a @@ ''!1 & 2''::anyquery')
+) v(pred), LATERAL anyarray_xcheck_match(pred);
+             pred             | gist_ok | gin_ok 
+------------------------------+---------+--------
+ a @> ARRAY[1,2]::int8[]      | t       | t
+ a @> ARRAY[100,200]::int8[]  | t       | t
+ a && ARRAY[5,99]::int8[]     | t       | t
+ a = ARRAY[1,2,3,4,5]::int8[] | t       | t
+ a @@ '1 & 2'::anyquery       | t       | t
+ a @@ '100 | 999'::anyquery   | t       | t
+ a @@ '!1 & 2'::anyquery      | t       | t
+(7 rows)
+
+-- Edge cases: empty / NULL arrays via index
+SET enable_seqscan = off;
+SELECT id FROM anyarray_xcheck WHERE a @> ARRAY[]::int8[] AND id = 1004;
+  id  
+------
+ 1004
+(1 row)
+
+SELECT id FROM anyarray_xcheck WHERE a <@ ARRAY[1,2,3]::int8[] AND id < 100 ORDER BY id LIMIT 3;
+ id 
+----
+  1
+ 15
+ 30
+(3 rows)
+
+SELECT count(*) FROM anyarray_xcheck WHERE a IS NULL;
+ count 
+-------
+     1
+(1 row)
+
+RESET enable_seqscan;
+-- DELETE / VACUUM / re-query through index
+DELETE FROM anyarray_xcheck WHERE id BETWEEN 1 AND 50;
+VACUUM anyarray_xcheck;
+SET enable_seqscan = off;
+SELECT count(*) FROM anyarray_xcheck WHERE a @@ '1 | 2'::anyquery;
+ count 
+-------
+    98
+(1 row)
+
+RESET enable_seqscan;
+DROP FUNCTION anyarray_xcheck_match(text);
diff --git a/contrib/anyarray/meson.build b/contrib/anyarray/meson.build
new file mode 100644
index 00000000000..a20646b82b2
--- /dev/null
+++ b/contrib/anyarray/meson.build
@@ -0,0 +1,38 @@
+# Copyright (c) 2026, PostgreSQL Global Development Group
+
+anyarray_sources = files(
+  'anyarray.c',
+  'anyarray_bool.c',
+  'anyarray_gin.c',
+  'anyarray_gist.c',
+  'anyarray_op.c',
+)
+
+if host_system == 'windows'
+  anyarray_sources += rc_lib_gen.process(win32ver_rc, extra_args: [
+    '--NAME', 'anyarray',
+    '--FILEDESC', 'anyarray - operations and indexes for arrays of any type',])
+endif
+
+anyarray = shared_module('anyarray',
+  anyarray_sources,
+  kwargs: contrib_mod_args,
+)
+contrib_targets += anyarray
+
+install_data(
+  'anyarray--1.0.sql',
+  'anyarray.control',
+  kwargs: contrib_data_args,
+)
+
+tests += {
+  'name': 'anyarray',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'regress': {
+    'sql': [
+      'anyarray',
+    ],
+  },
+}
diff --git a/contrib/anyarray/sql/anyarray.sql b/contrib/anyarray/sql/anyarray.sql
new file mode 100644
index 00000000000..90cc061fbde
--- /dev/null
+++ b/contrib/anyarray/sql/anyarray.sql
@@ -0,0 +1,330 @@
+CREATE EXTENSION anyarray;
+
+--
+-- Phase 1: set operations, helpers and operators for int8, uuid, text
+--
+
+-- ===== int8 =====
+SELECT anyarray_sort(ARRAY[3, 1, 2, 1]::int8[]);
+SELECT anyarray_sort(ARRAY[3, 1, 2, 1]::int8[], 'desc');
+SELECT anyarray_sort(ARRAY[]::int8[]);
+SELECT anyarray_uniq(ARRAY[1, 1, 2, 3, 3, 2]::int8[]);
+SELECT anyarray_idx(ARRAY[10, 20, 30]::int8[], 20::int8);
+SELECT anyarray_idx(ARRAY[10, 20, 30]::int8[], 99::int8);
+SELECT anyarray_subarray(ARRAY[1,2,3,4,5]::int8[], 2, 2);
+SELECT anyarray_subarray(ARRAY[1,2,3,4,5]::int8[], 3);
+SELECT anyarray_subarray(ARRAY[1,2,3]::int8[], 5, 1);
+
+SELECT ARRAY[1,2,3]::int8[] & ARRAY[2,3,4]::int8[];
+SELECT ARRAY[1,2,3]::int8[] | ARRAY[3,4,5]::int8[];
+SELECT ARRAY[1,2,3]::int8[] | 4::int8;
+SELECT ARRAY[1,2,3,4]::int8[] - ARRAY[2,4]::int8[];
+SELECT ARRAY[1,2,2,3,2]::int8[] - 2::int8;
+SELECT # ARRAY[10,20,30]::int8[];
+SELECT ARRAY[10,20,30]::int8[] # 20::int8;
+
+-- ===== uuid =====
+SELECT anyarray_sort(ARRAY[
+  '00000000-0000-0000-0000-000000000003'::uuid,
+  '00000000-0000-0000-0000-000000000001',
+  '00000000-0000-0000-0000-000000000002']);
+SELECT anyarray_uniq(ARRAY[
+  '00000000-0000-0000-0000-000000000001'::uuid,
+  '00000000-0000-0000-0000-000000000001',
+  '00000000-0000-0000-0000-000000000002']);
+SELECT anyarray_idx(ARRAY[
+  '00000000-0000-0000-0000-000000000001'::uuid,
+  '00000000-0000-0000-0000-000000000002'],
+  '00000000-0000-0000-0000-000000000002'::uuid);
+
+SELECT ARRAY['00000000-0000-0000-0000-000000000001'::uuid,
+             '00000000-0000-0000-0000-000000000002']
+     & ARRAY['00000000-0000-0000-0000-000000000002'::uuid,
+             '00000000-0000-0000-0000-000000000003'];
+
+SELECT ARRAY['00000000-0000-0000-0000-000000000001'::uuid]
+     | '00000000-0000-0000-0000-000000000002'::uuid;
+
+-- ===== text =====
+SELECT anyarray_sort(ARRAY['banana','apple','cherry']);
+SELECT anyarray_sort(ARRAY['banana','apple','cherry'], 'desc');
+SELECT anyarray_uniq(ARRAY['a','b','a','c','b']);
+SELECT anyarray_idx(ARRAY['a','b','c'], 'b'::text);
+SELECT ARRAY['a','b','c']::text[] & ARRAY['b','c','d']::text[];
+SELECT ARRAY['a','b','c']::text[] | 'd'::text;
+SELECT ARRAY['a','b','c','b']::text[] - 'b'::text;
+
+-- ===== error cases =====
+-- multi-dim
+SELECT anyarray_sort(ARRAY[[1,2],[3,4]]::int8[]);
+-- nulls
+SELECT anyarray_sort(ARRAY[1, NULL, 2]::int8[]);
+-- bad direction
+SELECT anyarray_sort(ARRAY[1,2,3]::int8[], 'bogus');
+
+--
+-- Phase 2: anyquery and @@ operator
+--
+
+-- parsing + output round-trip
+SELECT '1 & 2'::anyquery::text;
+SELECT '1 & 2 | 3'::anyquery::text;
+SELECT '(1 | 2) & 3'::anyquery::text;
+SELECT '!1 & 2'::anyquery::text;
+SELECT '!(1 | 2) & 3'::anyquery::text;
+SELECT '"hello world" | foo'::anyquery::text;
+SELECT anyquery_querytree('1 & 2 | 3'::anyquery);
+
+-- int8 matching
+SELECT ARRAY[1,2,3]::int8[] @@ '1'::anyquery;
+SELECT ARRAY[1,2,3]::int8[] @@ '1 & 2'::anyquery;
+SELECT ARRAY[1,2,3]::int8[] @@ '1 & 4'::anyquery;
+SELECT ARRAY[1,2,3]::int8[] @@ '1 | 4'::anyquery;
+SELECT ARRAY[1,2,3]::int8[] @@ '!4'::anyquery;
+SELECT ARRAY[1,2,3]::int8[] @@ '!1'::anyquery;
+SELECT ARRAY[1,2,3]::int8[] @@ '!4 & 1'::anyquery;
+SELECT ARRAY[1,2,3]::int8[] @@ '(1 | 4) & (2 | 5)'::anyquery;
+
+-- commutator
+SELECT '1 & 2'::anyquery ~~ ARRAY[1,2,3]::int8[];
+SELECT '1 & 4'::anyquery ~~ ARRAY[1,2,3]::int8[];
+
+-- uuid
+SELECT ARRAY['00000000-0000-0000-0000-000000000001'::uuid,
+             '00000000-0000-0000-0000-000000000002']
+       @@ '00000000-0000-0000-0000-000000000001 & 00000000-0000-0000-0000-000000000002'::anyquery;
+SELECT ARRAY['00000000-0000-0000-0000-000000000001'::uuid]
+       @@ '00000000-0000-0000-0000-000000000002'::anyquery;
+
+-- text
+SELECT ARRAY['apple','banana','cherry']::text[] @@ 'apple & banana'::anyquery;
+SELECT ARRAY['apple','banana','cherry']::text[] @@ '"banana" | grape'::anyquery;
+SELECT ARRAY['apple','banana','cherry']::text[] @@ 'durian | grape'::anyquery;
+
+-- empty array
+SELECT ARRAY[]::int8[] @@ '1'::anyquery;
+SELECT ARRAY[]::int8[] @@ '!1'::anyquery;
+
+-- parse errors
+SELECT ''::anyquery;
+SELECT '1 &'::anyquery;
+SELECT '1 & (2'::anyquery;
+SELECT '1 ) 2'::anyquery;
+
+-- runtime errors: token cannot be parsed as element type
+SELECT ARRAY[1,2]::int8[] @@ 'abc'::anyquery;
+
+--
+-- Phase 3: GiST signature index
+--
+
+-- amvalidate: well-formed opclass
+SELECT amname, opcname FROM pg_opclass opc
+LEFT JOIN pg_am am ON am.oid = opcmethod
+WHERE opc.opcname = 'anyarray_gist_ops' AND NOT amvalidate(opc.oid);
+
+-- int8 GiST: build deterministic table
+CREATE TABLE anyarray_gist_int8 (id int, a int8[]);
+INSERT INTO anyarray_gist_int8 VALUES
+  (1, ARRAY[1,2,3]::int8[]),
+  (2, ARRAY[10,20,30]::int8[]),
+  (3, ARRAY[10,20,30]::int8[]),
+  (4, ARRAY[1,2,3,4,5]::int8[]),
+  (5, ARRAY[100,200]::int8[]);
+
+CREATE INDEX anyarray_gist_int8_idx
+  ON anyarray_gist_int8 USING gist(a anyarray_gist_ops);
+
+SET enable_seqscan = off;
+
+SELECT id FROM anyarray_gist_int8 WHERE a @> ARRAY[1,2]::int8[] ORDER BY id;
+SELECT id FROM anyarray_gist_int8 WHERE a && ARRAY[10,200]::int8[] ORDER BY id;
+SELECT id FROM anyarray_gist_int8 WHERE a = ARRAY[10,20,30]::int8[] ORDER BY id;
+SELECT id FROM anyarray_gist_int8 WHERE a <@ ARRAY[1,2,3,4,5]::int8[] ORDER BY id;
+SELECT id FROM anyarray_gist_int8 WHERE a @@ '10 & 20'::anyquery ORDER BY id;
+SELECT id FROM anyarray_gist_int8 WHERE a @@ '1 | 100'::anyquery ORDER BY id;
+SELECT id FROM anyarray_gist_int8 WHERE a @@ '!1 & 10'::anyquery ORDER BY id;
+
+-- result consistency: GiST must agree with seqscan
+SELECT (
+  SELECT count(*) FROM anyarray_gist_int8 WHERE a @> ARRAY[10]::int8[]
+) = (
+  SELECT count(*) FROM (SELECT 1 FROM anyarray_gist_int8 WHERE a @> ARRAY[10]::int8[]) s
+) AS gist_matches_seqscan;
+
+RESET enable_seqscan;
+
+-- text GiST
+CREATE TABLE anyarray_gist_text (id int, a text[]);
+INSERT INTO anyarray_gist_text VALUES
+  (1, ARRAY['apple','banana']),
+  (2, ARRAY['banana','cherry']),
+  (3, ARRAY['apple','cherry','durian']);
+
+CREATE INDEX anyarray_gist_text_idx
+  ON anyarray_gist_text USING gist(a anyarray_gist_ops(siglen=64));
+
+SET enable_seqscan = off;
+SELECT id FROM anyarray_gist_text WHERE a @> ARRAY['apple']::text[] ORDER BY id;
+SELECT id FROM anyarray_gist_text WHERE a @@ 'apple & cherry'::anyquery ORDER BY id;
+RESET enable_seqscan;
+
+-- siglen bounds
+CREATE INDEX ON anyarray_gist_text USING gist(a anyarray_gist_ops(siglen=0));
+CREATE INDEX ON anyarray_gist_text USING gist(a anyarray_gist_ops(siglen=8193));
+
+--
+-- Phase 4: GIN index (per-type, supports standard ops + @@)
+--
+
+-- amvalidate: all three opclasses
+SELECT amname, opcname FROM pg_opclass opc
+LEFT JOIN pg_am am ON am.oid = opcmethod
+WHERE opc.opcname LIKE '%anyquery_gin_ops' AND NOT amvalidate(opc.oid);
+
+-- int8 GIN
+CREATE TABLE anyarray_gin_int8 (id int, a int8[]);
+INSERT INTO anyarray_gin_int8 VALUES
+  (1, ARRAY[1,2,3]::int8[]),
+  (2, ARRAY[10,20,30]::int8[]),
+  (3, ARRAY[10,20,30]::int8[]),
+  (4, ARRAY[1,2,3,4,5]::int8[]),
+  (5, ARRAY[100,200]::int8[]);
+
+CREATE INDEX anyarray_gin_int8_idx
+  ON anyarray_gin_int8 USING gin(a int8_anyquery_gin_ops);
+
+SET enable_seqscan = off;
+SELECT id FROM anyarray_gin_int8 WHERE a @> ARRAY[1,2]::int8[] ORDER BY id;
+SELECT id FROM anyarray_gin_int8 WHERE a && ARRAY[10,200]::int8[] ORDER BY id;
+SELECT id FROM anyarray_gin_int8 WHERE a @@ '10 & 20'::anyquery ORDER BY id;
+SELECT id FROM anyarray_gin_int8 WHERE a @@ '(1 & 2) | 100'::anyquery ORDER BY id;
+SELECT id FROM anyarray_gin_int8 WHERE a @@ '!1'::anyquery ORDER BY id;
+
+-- uuid GIN
+CREATE TABLE anyarray_gin_uuid (id int, a uuid[]);
+INSERT INTO anyarray_gin_uuid VALUES
+  (1, ARRAY['11111111-1111-1111-1111-111111111111'::uuid,
+            '22222222-2222-2222-2222-222222222222']),
+  (2, ARRAY['33333333-3333-3333-3333-333333333333'::uuid]),
+  (3, ARRAY['11111111-1111-1111-1111-111111111111'::uuid,
+            '33333333-3333-3333-3333-333333333333']);
+
+CREATE INDEX anyarray_gin_uuid_idx
+  ON anyarray_gin_uuid USING gin(a uuid_anyquery_gin_ops);
+
+SET enable_seqscan = off;
+SELECT id FROM anyarray_gin_uuid
+  WHERE a @@ '11111111-1111-1111-1111-111111111111 & 22222222-2222-2222-2222-222222222222'::anyquery
+  ORDER BY id;
+SELECT id FROM anyarray_gin_uuid
+  WHERE a @> ARRAY['11111111-1111-1111-1111-111111111111'::uuid]
+  ORDER BY id;
+RESET enable_seqscan;
+
+-- text GIN
+CREATE TABLE anyarray_gin_text (id int, a text[]);
+INSERT INTO anyarray_gin_text VALUES
+  (1, ARRAY['apple','banana']),
+  (2, ARRAY['banana','cherry']),
+  (3, ARRAY['apple','cherry','durian']);
+
+CREATE INDEX anyarray_gin_text_idx
+  ON anyarray_gin_text USING gin(a text_anyquery_gin_ops);
+
+SET enable_seqscan = off;
+SELECT id FROM anyarray_gin_text WHERE a @@ 'apple & cherry'::anyquery ORDER BY id;
+SELECT id FROM anyarray_gin_text WHERE a @@ '"durian"'::anyquery ORDER BY id;
+SELECT id FROM anyarray_gin_text WHERE a @@ 'apple | grape'::anyquery ORDER BY id;
+SELECT id FROM anyarray_gin_text WHERE a @@ '!banana'::anyquery ORDER BY id;
+RESET enable_seqscan;
+
+--
+-- Phase 5: cross-AM consistency and edge cases
+--
+-- Build a larger deterministic int8 table and index it with both GiST and
+-- GIN.  Then run each candidate query under seqscan, GiST and GIN and check
+-- that all three plans return the same row set.
+--
+
+CREATE TABLE anyarray_xcheck (id int, a int8[]);
+
+INSERT INTO anyarray_xcheck
+SELECT g,
+       ARRAY[(g % 7)::int8, ((g * 3) % 11)::int8, ((g + 1) % 5)::int8]
+FROM generate_series(1, 200) g;
+-- a few hand-picked rows to exercise common values
+INSERT INTO anyarray_xcheck VALUES
+  (1001, ARRAY[1,2,3,4,5]::int8[]),
+  (1002, ARRAY[1,2,3,4,5]::int8[]),
+  (1003, ARRAY[100,200,300]::int8[]),
+  (1004, ARRAY[]::int8[]),
+  (1005, NULL);
+
+CREATE INDEX anyarray_xcheck_gist ON anyarray_xcheck
+  USING gist(a anyarray_gist_ops);
+CREATE INDEX anyarray_xcheck_gin ON anyarray_xcheck
+  USING gin(a int8_anyquery_gin_ops);
+
+-- Run each predicate three times: pure seqscan, GiST-only, GIN-only.
+-- All three result sets must match.
+CREATE FUNCTION anyarray_xcheck_match(pred text)
+RETURNS TABLE(gist_ok bool, gin_ok bool)
+LANGUAGE plpgsql AS $$
+DECLARE
+  seq int[]; gst int[]; gin int[];
+BEGIN
+  SET LOCAL enable_seqscan = on;
+  SET LOCAL enable_indexscan = off;
+  SET LOCAL enable_bitmapscan = off;
+  EXECUTE 'SELECT array_agg(id ORDER BY id) FROM anyarray_xcheck WHERE '
+          || pred INTO seq;
+
+  -- Force GiST by hiding the GIN index.
+  ALTER INDEX anyarray_xcheck_gin SET (fastupdate = off);
+  SET LOCAL enable_seqscan = off;
+  SET LOCAL enable_indexscan = on;
+  SET LOCAL enable_bitmapscan = on;
+  DROP INDEX anyarray_xcheck_gin;
+  EXECUTE 'SELECT array_agg(id ORDER BY id) FROM anyarray_xcheck WHERE '
+          || pred INTO gst;
+  CREATE INDEX anyarray_xcheck_gin ON anyarray_xcheck
+    USING gin(a int8_anyquery_gin_ops);
+
+  -- Force GIN by hiding GiST.
+  DROP INDEX anyarray_xcheck_gist;
+  EXECUTE 'SELECT array_agg(id ORDER BY id) FROM anyarray_xcheck WHERE '
+          || pred INTO gin;
+  CREATE INDEX anyarray_xcheck_gist ON anyarray_xcheck
+    USING gist(a anyarray_gist_ops);
+
+  gist_ok := seq IS NOT DISTINCT FROM gst;
+  gin_ok  := seq IS NOT DISTINCT FROM gin;
+  RETURN NEXT;
+END $$;
+
+SELECT pred, gist_ok, gin_ok FROM (VALUES
+  ('a @> ARRAY[1,2]::int8[]'),
+  ('a @> ARRAY[100,200]::int8[]'),
+  ('a && ARRAY[5,99]::int8[]'),
+  ('a = ARRAY[1,2,3,4,5]::int8[]'),
+  ('a @@ ''1 & 2''::anyquery'),
+  ('a @@ ''100 | 999''::anyquery'),
+  ('a @@ ''!1 & 2''::anyquery')
+) v(pred), LATERAL anyarray_xcheck_match(pred);
+
+-- Edge cases: empty / NULL arrays via index
+SET enable_seqscan = off;
+SELECT id FROM anyarray_xcheck WHERE a @> ARRAY[]::int8[] AND id = 1004;
+SELECT id FROM anyarray_xcheck WHERE a <@ ARRAY[1,2,3]::int8[] AND id < 100 ORDER BY id LIMIT 3;
+SELECT count(*) FROM anyarray_xcheck WHERE a IS NULL;
+RESET enable_seqscan;
+
+-- DELETE / VACUUM / re-query through index
+DELETE FROM anyarray_xcheck WHERE id BETWEEN 1 AND 50;
+VACUUM anyarray_xcheck;
+SET enable_seqscan = off;
+SELECT count(*) FROM anyarray_xcheck WHERE a @@ '1 | 2'::anyquery;
+RESET enable_seqscan;
+
+DROP FUNCTION anyarray_xcheck_match(text);
diff --git a/contrib/meson.build b/contrib/meson.build
index ebb7f83d8c5..e158f18fa7e 100644
--- a/contrib/meson.build
+++ b/contrib/meson.build
@@ -13,6 +13,7 @@ contrib_doc_args = {
 }
 
 subdir('amcheck')
+subdir('anyarray')
 subdir('auth_delay')
 subdir('auto_explain')
 subdir('basic_archive')
diff --git a/doc/src/sgml/anyarray.sgml b/doc/src/sgml/anyarray.sgml
new file mode 100644
index 00000000000..4f376e0868c
--- /dev/null
+++ b/doc/src/sgml/anyarray.sgml
@@ -0,0 +1,482 @@
+<!-- doc/src/sgml/anyarray.sgml -->
+
+<sect1 id="anyarray" xreflabel="anyarray">
+ <title>anyarray &mdash; operations and indexes for arrays of any type</title>
+
+ <indexterm zone="anyarray">
+  <primary>anyarray</primary>
+ </indexterm>
+
+ <para>
+  The <filename>anyarray</filename> module generalizes
+  <xref linkend="intarray"/>-style operations to arrays of any element type
+  that provides a default B-tree opclass.  It adds set-style helpers, a
+  textual boolean query type (<type>anyquery</type>), and index support that
+  works for arbitrary element types.
+ </para>
+
+ <para>
+  All operations reject arrays that contain <literal>NULL</literal> elements,
+  and they are defined only for one-dimensional arrays.
+ </para>
+
+ <para>
+  This module is not marked as <quote>trusted</quote>: installing it
+  requires database-level privileges, because the index operator classes
+  it defines refer to internal storage types.
+ </para>
+
+ <sect2 id="anyarray-funcs-ops">
+  <title><filename>anyarray</filename> Functions and Operators</title>
+
+  <para>
+   The functions provided by <filename>anyarray</filename> are listed in
+   <xref linkend="anyarray-func-table"/>, the operators in
+   <xref linkend="anyarray-op-table"/>.
+  </para>
+
+  <table id="anyarray-func-table">
+   <title><filename>anyarray</filename> Functions</title>
+    <tgroup cols="1">
+     <thead>
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
+        Function
+       </para>
+       <para>
+        Description
+       </para>
+       <para>
+        Example(s)
+       </para></entry>
+      </row>
+     </thead>
+
+     <tbody>
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
+        <function>anyarray_sort</function> ( <type>anyarray</type> [, <type>text</type> ] )
+        <returnvalue>anyarray</returnvalue>
+       </para>
+       <para>
+        Sorts an array.  The optional second argument is
+        <literal>asc</literal> (default) or <literal>desc</literal>.
+       </para>
+       <para>
+        <literal>anyarray_sort('{3,1,2}'::int8[])</literal>
+        <returnvalue>{1,2,3}</returnvalue>
+       </para></entry>
+      </row>
+
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
+        <function>anyarray_uniq</function> ( <type>anyarray</type> )
+        <returnvalue>anyarray</returnvalue>
+       </para>
+       <para>
+        Removes duplicates from the array, returning the sorted unique
+        elements.
+       </para>
+       <para>
+        <literal>anyarray_uniq('{1,1,2,3,3}'::int8[])</literal>
+        <returnvalue>{1,2,3}</returnvalue>
+       </para></entry>
+      </row>
+
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
+        <function>anyarray_idx</function> ( <type>anyarray</type>, <type>anyelement</type> )
+        <returnvalue>integer</returnvalue>
+       </para>
+       <para>
+        Returns the 1-based index of the first occurrence of the element,
+        or 0 if not found.
+       </para>
+       <para>
+        <literal>anyarray_idx(ARRAY['a','b','c'], 'b')</literal>
+        <returnvalue>2</returnvalue>
+       </para></entry>
+      </row>
+
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
+        <function>anyarray_subarray</function> ( <type>anyarray</type>, <parameter>start</parameter> <type>integer</type> [, <parameter>length</parameter> <type>integer</type> ] )
+        <returnvalue>anyarray</returnvalue>
+       </para>
+       <para>
+        Returns a contiguous slice starting at <parameter>start</parameter>
+        (1-based).  If <parameter>length</parameter> is omitted the slice
+        extends to the end of the array.  Out-of-range positions or
+        non-positive lengths produce an empty array.
+       </para>
+       <para>
+        <literal>anyarray_subarray('{1,2,3,4,5}'::int8[], 2, 2)</literal>
+        <returnvalue>{2,3}</returnvalue>
+       </para></entry>
+      </row>
+
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
+        <function>anyarray_icount</function> ( <type>anyarray</type> )
+        <returnvalue>integer</returnvalue>
+       </para>
+       <para>
+        Returns the number of elements in the array (exposed under the
+        <literal>#</literal> operator).
+       </para>
+       <para>
+        <literal>anyarray_icount('{10,20,30}'::int8[])</literal>
+        <returnvalue>3</returnvalue>
+       </para></entry>
+      </row>
+
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
+        <function>anyarray_intersect</function> ( <type>anyarray</type>, <type>anyarray</type> )
+        <returnvalue>anyarray</returnvalue>
+       </para>
+       <para>
+        Returns the sorted, deduplicated values present in both inputs.
+       </para>
+       <para>
+        <literal>anyarray_intersect('{1,2,3}'::int8[], '{2,3,4}')</literal>
+        <returnvalue>{2,3}</returnvalue>
+       </para></entry>
+      </row>
+
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
+        <function>anyarray_union</function> ( <type>anyarray</type>, <type>anyarray</type> )
+        <returnvalue>anyarray</returnvalue>
+       </para>
+       <para>
+        Returns the sorted, deduplicated union of both inputs.
+       </para>
+       <para>
+        <literal>anyarray_union('{1,2}'::int8[], '{2,3}')</literal>
+        <returnvalue>{1,2,3}</returnvalue>
+       </para></entry>
+      </row>
+
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
+        <function>anyarray_union_elem</function> ( <type>anyarray</type>, <type>anyelement</type> )
+        <returnvalue>anyarray</returnvalue>
+       </para>
+       <para>
+        Adds an element to the array if not already present; result is
+        sorted and deduplicated.
+       </para>
+       <para>
+        <literal>anyarray_union_elem('{1,2,3}'::int8[], 4::int8)</literal>
+        <returnvalue>{1,2,3,4}</returnvalue>
+       </para></entry>
+      </row>
+
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
+        <function>anyarray_difference</function> ( <type>anyarray</type>, <type>anyarray</type> )
+        <returnvalue>anyarray</returnvalue>
+       </para>
+       <para>
+        Returns the sorted, deduplicated values from the first array that
+        are not in the second.
+       </para>
+       <para>
+        <literal>anyarray_difference('{1,2,3,4}'::int8[], '{2,4}')</literal>
+        <returnvalue>{1,3}</returnvalue>
+       </para></entry>
+      </row>
+
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
+        <function>anyarray_difference_elem</function> ( <type>anyarray</type>, <type>anyelement</type> )
+        <returnvalue>anyarray</returnvalue>
+       </para>
+       <para>
+        Removes all occurrences of the given element, preserving the
+        relative order of the surviving elements.
+       </para>
+       <para>
+        <literal>anyarray_difference_elem('{1,2,2,3,2}'::int8[], 2::int8)</literal>
+        <returnvalue>{1,3}</returnvalue>
+       </para></entry>
+      </row>
+
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
+        <function>anyquery_querytree</function> ( <type>anyquery</type> )
+        <returnvalue>text</returnvalue>
+       </para>
+       <para>
+        Returns the query in postfix form; useful for debugging.
+       </para>
+       <para>
+        <literal>anyquery_querytree('1 &amp; 2 | 3'::anyquery)</literal>
+        <returnvalue>1 2 &amp; 3 |</returnvalue>
+       </para></entry>
+      </row>
+     </tbody>
+    </tgroup>
+   </table>
+
+   <table id="anyarray-op-table">
+    <title><filename>anyarray</filename> Operators</title>
+     <tgroup cols="1">
+      <thead>
+       <row>
+        <entry role="func_table_entry"><para role="func_signature">
+         Operator
+        </para>
+        <para>
+         Description
+        </para></entry>
+       </row>
+      </thead>
+
+      <tbody>
+       <row>
+        <entry role="func_table_entry"><para role="func_signature">
+         <type></type> <literal>#</literal> <type>anyarray</type>
+         <returnvalue>integer</returnvalue>
+        </para>
+        <para>
+         Returns the number of elements in the array (prefix operator).
+        </para></entry>
+       </row>
+
+       <row>
+        <entry role="func_table_entry"><para role="func_signature">
+         <type>anyarray</type> <literal>#</literal> <type>anyelement</type>
+         <returnvalue>integer</returnvalue>
+        </para>
+        <para>
+         Returns the 1-based index of the right operand in the array, or 0
+         if not found.  Same as <function>anyarray_idx</function>.
+        </para></entry>
+       </row>
+
+       <row>
+        <entry role="func_table_entry"><para role="func_signature">
+         <type>anyarray</type> <literal>&amp;</literal> <type>anyarray</type>
+         <returnvalue>anyarray</returnvalue>
+        </para>
+        <para>
+         Set intersection of the operands.
+        </para></entry>
+       </row>
+
+       <row>
+        <entry role="func_table_entry"><para role="func_signature">
+         <type>anyarray</type> <literal>|</literal> <type>anyarray</type>
+         <returnvalue>anyarray</returnvalue>
+        </para>
+        <para>
+         Set union of the operands.
+        </para></entry>
+       </row>
+
+       <row>
+        <entry role="func_table_entry"><para role="func_signature">
+         <type>anyarray</type> <literal>|</literal> <type>anyelement</type>
+         <returnvalue>anyarray</returnvalue>
+        </para>
+        <para>
+         Adds the right operand to the array if not already present.
+        </para></entry>
+       </row>
+
+       <row>
+        <entry role="func_table_entry"><para role="func_signature">
+         <type>anyarray</type> <literal>-</literal> <type>anyarray</type>
+         <returnvalue>anyarray</returnvalue>
+        </para>
+        <para>
+         Set difference: elements of the left array not present in the
+         right.
+        </para></entry>
+       </row>
+
+       <row>
+        <entry role="func_table_entry"><para role="func_signature">
+         <type>anyarray</type> <literal>-</literal> <type>anyelement</type>
+         <returnvalue>anyarray</returnvalue>
+        </para>
+        <para>
+         Removes all occurrences of the right operand from the array.
+        </para></entry>
+       </row>
+
+       <row>
+        <entry role="func_table_entry"><para role="func_signature">
+         <type>anyarray</type> <literal>@@</literal> <type>anyquery</type>
+         <returnvalue>boolean</returnvalue>
+        </para>
+        <para>
+         True if the array satisfies the query (see below).
+        </para></entry>
+       </row>
+
+       <row>
+        <entry role="func_table_entry"><para role="func_signature">
+         <type>anyquery</type> <literal>~~</literal> <type>anyarray</type>
+         <returnvalue>boolean</returnvalue>
+        </para>
+        <para>
+         Commutator of <literal>@@</literal>.
+        </para></entry>
+       </row>
+      </tbody>
+     </tgroup>
+   </table>
+
+   <para>
+    The operators <literal>&amp;&amp;</literal>, <literal>@&gt;</literal>,
+    <literal>&lt;@</literal> and <literal>=</literal> on arrays are
+    <emphasis>not</emphasis> redefined by this extension; the built-in
+    PostgreSQL operators are used.
+   </para>
+ </sect2>
+
+ <sect2 id="anyarray-query">
+  <title>The <type>anyquery</type> Type</title>
+
+  <para>
+   <type>anyquery</type> represents a boolean expression over array
+   elements.  Values are textual tokens; the element type used to interpret
+   them is determined by the left-hand side of <literal>@@</literal> at
+   query time.  Tokens are combined with the operators
+   <literal>&amp;</literal> (AND), <literal>|</literal> (OR) and
+   <literal>!</literal> (NOT).  Parentheses control precedence; without
+   them <literal>&amp;</literal> binds tighter than <literal>|</literal>.
+  </para>
+
+  <para>
+   A token consists of any sequence of characters that are not whitespace
+   or one of <literal>&amp; | ! ( ) "</literal>.  To include those
+   characters or embedded whitespace, wrap the token in double quotes:
+   <literal>"hello world"</literal>.  Inside quotes, a backslash escapes
+   the next character.
+  </para>
+
+  <para>
+   At evaluation time, each token is parsed by the input function of the
+   array's element type.  This means
+   <literal>'1 &amp; 2'::anyquery @@ ARRAY[1,2,3]::bigint[]</literal>
+   parses <quote>1</quote> and <quote>2</quote> as <type>bigint</type>; the
+   same query against a <type>text[]</type> column compares the literal
+   strings <quote>1</quote> and <quote>2</quote>.  An unparseable token
+   raises an error at <literal>@@</literal>-time, not at parse time.
+  </para>
+ </sect2>
+
+ <sect2 id="anyarray-index">
+  <title>Index Support</title>
+
+  <para>
+   <filename>anyarray</filename> provides a polymorphic GiST opclass and
+   per-element-type GIN opclasses.  All of them support the standard array
+   operators (<literal>&amp;&amp;</literal>, <literal>@&gt;</literal>,
+   <literal>&lt;@</literal>, <literal>=</literal>) as well as
+   <literal>@@</literal>.
+  </para>
+
+  <sect3 id="anyarray-index-gist">
+   <title>GiST: <literal>anyarray_gist_ops</literal></title>
+
+   <para>
+    A single opclass on <type>anyarray</type> works for any element type
+    that has a default hash function.  Each indexed array is summarised as
+    a fixed-size bit vector by hashing every element into one bit; internal
+    nodes store the union of their children.  All matches are rechecked
+    because signatures are lossy.
+   </para>
+
+   <para>
+    The optional integer parameter <literal>siglen</literal> sets the
+    signature length in bytes.  The default is 252 bytes (2016 bits);
+    valid values are between 1 and the index-key size limit.  Longer
+    signatures produce more precise indexes at the cost of more storage.
+   </para>
+
+   <programlisting>
+CREATE INDEX my_idx ON my_table USING gist (col anyarray_gist_ops);
+CREATE INDEX my_idx ON my_table USING gist (col anyarray_gist_ops(siglen=64));
+   </programlisting>
+  </sect3>
+
+  <sect3 id="anyarray-index-gin">
+   <title>GIN: per-type opclasses</title>
+
+   <para>
+    Because the GIN extractQuery API does not expose the indexed column's
+    element type when the query is an <type>anyquery</type>, GIN support
+    is provided as one opclass per concrete element type.  Currently
+    supplied:
+   </para>
+
+   <itemizedlist>
+    <listitem><para>
+     <literal>int8_anyquery_gin_ops</literal> for <type>bigint[]</type>
+    </para></listitem>
+    <listitem><para>
+     <literal>uuid_anyquery_gin_ops</literal> for <type>uuid[]</type>
+    </para></listitem>
+    <listitem><para>
+     <literal>text_anyquery_gin_ops</literal> for <type>text[]</type>
+    </para></listitem>
+   </itemizedlist>
+
+   <para>
+    These opclasses are drop-in replacements for the built-in
+    <literal>array_ops</literal>; they additionally support
+    <literal>@@</literal>.
+   </para>
+
+   <programlisting>
+CREATE INDEX my_idx ON my_table USING gin (col int8_anyquery_gin_ops);
+   </programlisting>
+
+   <para>
+    For element types not in the list above, use the built-in GIN
+    <literal>array_ops</literal> for set queries and rely on
+    <literal>anyarray_gist_ops</literal> for <literal>@@</literal>.
+   </para>
+  </sect3>
+ </sect2>
+
+ <sect2 id="anyarray-example">
+  <title>Example</title>
+
+<programlisting>
+CREATE EXTENSION anyarray;
+
+CREATE TABLE message (mid INT PRIMARY KEY, tags TEXT[]);
+
+CREATE INDEX message_tags_gist ON message USING gist (tags anyarray_gist_ops);
+CREATE INDEX message_tags_gin  ON message USING gin  (tags text_anyquery_gin_ops);
+
+-- Messages tagged with both 'urgent' and 'bug':
+SELECT mid FROM message WHERE tags @&gt; ARRAY['urgent','bug'];
+
+-- Same, with the query syntax:
+SELECT mid FROM message WHERE tags @@ 'urgent &amp; bug'::anyquery;
+
+-- Messages tagged 'urgent' but not 'wontfix':
+SELECT mid FROM message WHERE tags @@ 'urgent &amp; !wontfix'::anyquery;
+
+-- Sort and deduplicate a tag list:
+SELECT anyarray_uniq(tags) FROM message WHERE mid = 42;
+</programlisting>
+ </sect2>
+
+ <sect2 id="anyarray-authors">
+  <title>Authors</title>
+
+  <para>
+   The <filename>anyarray</filename> module is a generalization of
+   <xref linkend="intarray"/> by Teodor Sigaev and Oleg Bartunov.
+  </para>
+ </sect2>
+
+</sect1>
diff --git a/doc/src/sgml/contrib.sgml b/doc/src/sgml/contrib.sgml
index b9b03654aad..c9aaf79cb69 100644
--- a/doc/src/sgml/contrib.sgml
+++ b/doc/src/sgml/contrib.sgml
@@ -128,6 +128,7 @@ CREATE EXTENSION <replaceable>extension_name</replaceable>;
  </para>
 
  &amcheck;
+ &anyarray;
  &auth-delay;
  &auto-explain;
  &basebackup-to-shell;
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 25a85082759..0530342e74b 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -119,6 +119,7 @@
 <!-- contrib information -->
 <!ENTITY contrib         SYSTEM "contrib.sgml">
 <!ENTITY amcheck         SYSTEM "amcheck.sgml">
+<!ENTITY anyarray        SYSTEM "anyarray.sgml">
 <!ENTITY auth-delay      SYSTEM "auth-delay.sgml">
 <!ENTITY auto-explain    SYSTEM "auto-explain.sgml">
 <!ENTITY basic-archive   SYSTEM "basic-archive.sgml">
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index cbd9e10fc1d..049485f5c24 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -126,7 +126,13 @@ AnalyzeAttrFetchFunc
 AnalyzeForeignTable_function
 AnlExprData
 AnlIndexData
+AnyArrayGistKey
+AnyArrayGistOptions
 AnyArrayType
+AnyArrayTypeInfo
+AnyQuery
+AnyQueryCheck
+AnyQueryItem
 Append
 AppendPath
 AppendPathInput
@@ -1744,6 +1750,7 @@ MVNDistinct
 MVNDistinctItem
 ManyTestResource
 ManyTestResourceKind
+MatchContext
 Material
 MaterialPath
 MaterialState
@@ -2372,6 +2379,7 @@ PgXmlStrictness
 Pg_abi_values
 Pg_finfo_record
 Pg_magic_struct
+PickSplitEntry
 PipeProtoChunk
 PipeProtoHeader
 PlaceHolderInfo
-- 
2.39.5 (Apple Git-154)



^ permalink  raw  reply  [nested|flat] 3+ messages in thread


end of thread, other threads:[~2026-05-20 15:19 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2026-05-18 10:17 [PATCH] Add contrib/anyarray: intarray-style operations and indexes for any array type Влад Медведицков <[email protected]>
2026-05-20 02:24 ` David G. Johnston <[email protected]>
2026-05-20 15:19   ` Влад Медведицков <[email protected]>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox