emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

scratch/comp-static-data 843fba7898d 1/2: Merge branch 'master' into scr


From: Vibhav Pant
Subject: scratch/comp-static-data 843fba7898d 1/2: Merge branch 'master' into scratch/comp-static-data
Date: Fri, 10 Feb 2023 07:22:25 -0500 (EST)

branch: scratch/comp-static-data
commit 843fba7898d72c07c4d5229bc5cdc5908aa140e7
Merge: dfee4b1464f 013655811aa
Author: Vibhav Pant <vibhavp@gmail.com>
Commit: Vibhav Pant <vibhavp@gmail.com>

    Merge branch 'master' into scratch/comp-static-data
---
 CONTRIBUTE                                         |    2 +-
 INSTALL.REPO                                       |    2 +-
 admin/MAINTAINERS                                  |    4 +-
 admin/merge-gnulib                                 |    6 +-
 admin/notes/elpa                                   |    2 +-
 admin/notes/tree-sitter/treesit_record_change      |   50 +
 build-aux/config.guess                             |    6 +-
 build-aux/config.sub                               |    8 +-
 doc/emacs/basic.texi                               |   49 +-
 doc/emacs/building.texi                            |   46 +-
 doc/emacs/display.texi                             |  131 +-
 doc/emacs/emacs.texi                               |    4 +
 doc/emacs/files.texi                               |   11 +
 doc/emacs/frames.texi                              |    1 +
 doc/emacs/misc.texi                                |   12 +-
 doc/emacs/programs.texi                            |   42 +-
 doc/emacs/text.texi                                |   12 +-
 doc/lispref/internals.texi                         |   21 +-
 doc/lispref/variables.texi                         |    1 +
 doc/misc/eshell.texi                               |   28 +-
 doc/misc/tramp.texi                                |    2 +-
 doc/misc/transient.texi                            |   20 +-
 etc/NEWS                                           |    7 +
 etc/NEWS.29                                        |   32 +
 lib/_Noreturn.h                                    |    5 +
 lib/cdefs.h                                        |   40 +-
 lib/fpending.c                                     |    2 +-
 lib/gnulib.mk.in                                   |   66 +-
 lib/inttypes.in.h                                  |   34 +-
 lib/libc-config.h                                  |   22 +-
 lib/openat-proc.c                                  |   27 +-
 lib/stdalign.in.h                                  |  133 --
 lib/stdio-impl.h                                   |    8 +-
 lib/stdio.in.h                                     |    6 +-
 lib/stdlib.in.h                                    |  141 +-
 lib/string.in.h                                    |   42 +-
 lib/sys_stat.in.h                                  |    8 +-
 lib/time.in.h                                      |   18 +-
 lib/unistd.in.h                                    |   80 +-
 lib/verify.h                                       |   17 +-
 lisp/bindings.el                                   |    6 +-
 lisp/emacs-lisp/byte-opt.el                        | 1493 +++++++++++---------
 lisp/emacs-lisp/bytecomp.el                        |   50 +-
 lisp/emacs-lisp/cconv.el                           |   11 +-
 lisp/emacs-lisp/comp.el                            |    7 +-
 lisp/emacs-lisp/lisp-mode.el                       |    1 +
 lisp/emacs-lisp/nadvice.el                         |   30 +-
 lisp/emacs-lisp/oclosure.el                        |    2 +-
 lisp/emacs-lisp/range.el                           |    8 +-
 lisp/eshell/em-cmpl.el                             |  101 +-
 lisp/eshell/esh-cmd.el                             |    2 +-
 lisp/eshell/esh-util.el                            |   23 +-
 lisp/eshell/esh-var.el                             |  136 +-
 lisp/faces.el                                      |   11 +-
 lisp/gnus/gnus-search.el                           |    7 +-
 lisp/isearch.el                                    |    9 +-
 lisp/keymap.el                                     |   53 +-
 lisp/ldefs-boot.el                                 |   76 +-
 lisp/net/tramp-adb.el                              |   18 +-
 lisp/net/tramp-archive.el                          |   33 +-
 lisp/net/tramp-container.el                        |   23 +-
 lisp/net/tramp-sh.el                               |   24 +-
 lisp/net/tramp-smb.el                              |    2 +-
 lisp/net/tramp-sudoedit.el                         |    2 +-
 lisp/net/tramp.el                                  |   53 +-
 lisp/org/ChangeLog.1                               |    2 +-
 lisp/org/org-agenda.el                             |    8 +-
 lisp/org/org-macs.el                               |    2 +-
 lisp/org/org-version.el                            |    2 +-
 lisp/org/org.el                                    |    1 +
 lisp/org/ox.el                                     |    4 +-
 lisp/progmodes/c-ts-common.el                      |  118 +-
 lisp/progmodes/c-ts-mode.el                        |  224 ++-
 lisp/progmodes/cc-defs.el                          |    7 +-
 lisp/progmodes/cc-engine.el                        |   72 +-
 lisp/progmodes/dockerfile-ts-mode.el               |   20 +-
 lisp/progmodes/go-ts-mode.el                       |    1 +
 lisp/progmodes/hideshow.el                         |    4 +
 lisp/progmodes/java-ts-mode.el                     |    1 +
 lisp/progmodes/js.el                               |   13 +-
 lisp/progmodes/project.el                          |    7 +-
 lisp/progmodes/python.el                           |    4 +-
 lisp/progmodes/ruby-ts-mode.el                     |   10 +-
 lisp/progmodes/rust-ts-mode.el                     |   27 +
 lisp/progmodes/typescript-ts-mode.el               |   12 +-
 lisp/repeat.el                                     |   48 +-
 lisp/simple.el                                     |   31 +-
 lisp/tab-bar.el                                    |    4 +-
 lisp/transient.el                                  |   40 +-
 lisp/treesit.el                                    |  110 +-
 lisp/window.el                                     |    5 +-
 m4/canonicalize.m4                                 |    8 +-
 m4/euidaccess.m4                                   |    4 +-
 m4/faccessat.m4                                    |    7 +-
 m4/fchmodat.m4                                     |    4 +-
 m4/futimens.m4                                     |    7 +-
 m4/getloadavg.m4                                   |   14 +-
 m4/getrandom.m4                                    |    5 +-
 m4/gettime.m4                                      |   35 +-
 m4/gnulib-common.m4                                |  403 ++++--
 m4/gnulib-comp.m4                                  |   23 +-
 m4/inttypes.m4                                     |    6 +-
 m4/mempcpy.m4                                      |    7 +-
 m4/mkostemp.m4                                     |    7 +-
 m4/nproc.m4                                        |    6 +-
 m4/pipe2.m4                                        |    9 +-
 m4/readlinkat.m4                                   |    7 +-
 m4/stdalign.m4                                     |  176 ++-
 m4/stddef_h.m4                                     |   11 +-
 m4/stdlib_h.m4                                     |   13 +-
 m4/stpcpy.m4                                       |    7 +-
 m4/string_h.m4                                     |    4 +-
 m4/time_h.m4                                       |    3 +-
 m4/timegm.m4                                       |    7 +-
 m4/unistd_h.m4                                     |    7 +-
 m4/utimens.m4                                      |    6 +-
 m4/utimensat.m4                                    |    7 +-
 nt/INSTALL.W64                                     |    2 +-
 src/comp.c                                         |    5 +-
 src/dispnew.c                                      |    4 +
 src/floatfns.c                                     |    7 +-
 src/insdel.c                                       |   19 +-
 src/lisp.h                                         |   10 +-
 src/search.c                                       |    5 +-
 src/sqlite.c                                       |   10 +-
 src/treesit.c                                      |  118 +-
 src/xdisp.c                                        |    2 +-
 src/xfaces.c                                       |    3 +-
 test/lisp/emacs-lisp/nadvice-tests.el              |   14 +-
 test/lisp/eshell/em-cmpl-tests.el                  |  208 +++
 test/lisp/eshell/esh-util-tests.el                 |   65 +
 test/lisp/eshell/esh-var-tests.el                  |  102 +-
 test/lisp/net/tramp-tests.el                       |   17 +-
 .../progmodes/c-ts-mode-resources/indent-bsd.erts  |    6 +-
 .../lisp/progmodes/c-ts-mode-resources/indent.erts |   66 +-
 .../progmodes/java-ts-mode-resources/indent.erts   |    9 +
 test/lisp/progmodes/project-tests.el               |   10 +
 137 files changed, 3694 insertions(+), 1887 deletions(-)

diff --git a/CONTRIBUTE b/CONTRIBUTE
index 674b4e5b18c..dcf34f48fe5 100644
--- a/CONTRIBUTE
+++ b/CONTRIBUTE
@@ -18,7 +18,7 @@ To configure Git for Emacs development, you can run the 
following:
 
 The following shell commands then build and run Emacs from scratch:
 
-       git clone git://git.sv.gnu.org/emacs.git
+       git clone https://git.savannah.gnu.org/git/emacs.git
        cd emacs
        ./autogen.sh
        ./configure
diff --git a/INSTALL.REPO b/INSTALL.REPO
index dcbbbcb9594..ea88842cfa9 100644
--- a/INSTALL.REPO
+++ b/INSTALL.REPO
@@ -4,7 +4,7 @@ The Emacs repository is hosted on Savannah.  The following Git 
command
 will clone the repository to the 'emacs' subdirectory of the current
 directory on your local machine:
 
-    git clone git://git.sv.gnu.org/emacs.git
+    git clone https://git.savannah.gnu.org/git/emacs.git
 
 To build the repository code, simply run 'make' in the 'emacs'
 directory.  This should work if your files are freshly checked out
diff --git a/admin/MAINTAINERS b/admin/MAINTAINERS
index 6e080d1f5bb..1273e9a976b 100644
--- a/admin/MAINTAINERS
+++ b/admin/MAINTAINERS
@@ -294,7 +294,7 @@ Po Lu
 
 Tramp
        Maintainer: Michael Albinus
-       Repository: git://git.savannah.gnu.org/tramp.git
+       Repository: https://git.savannah.gnu.org/git/tramp.git
        Mailing List: tramp-devel@gnu.org
        Bug Reports: M-x tramp-bug
        Notes: For backward compatibility requirements, see
@@ -316,7 +316,7 @@ Modus themes
 Org Mode
        Home Page: https://orgmode.org/
        Maintainer: Org Mode developers
-       Repository: git://git.sv.gnu.org/emacs/org-mode.git
+       Repository: https://git.savannah.gnu.org/git/emacs/org-mode.git
        Mailing list: emacs-orgmode@gnu.org
        Bug Reports: M-x org-submit-bug-report
        Notes: Org Mode is maintained as a separate project that is
diff --git a/admin/merge-gnulib b/admin/merge-gnulib
index f47c5e6e8d4..04e3e34b9f9 100755
--- a/admin/merge-gnulib
+++ b/admin/merge-gnulib
@@ -23,10 +23,10 @@
 
 # written by Paul Eggert
 
-GNULIB_URL=git://git.savannah.gnu.org/gnulib.git
+GNULIB_URL=https://git.savannah.gnu.org/git/gnulib.git
 
 GNULIB_MODULES='
-  alloca-opt binary-io byteswap c-ctype c-strcase
+  alignasof alloca-opt binary-io byteswap c-ctype c-strcase
   canonicalize-lgpl
   careadlinkat close-stream copy-file-range
   count-leading-zeros count-one-bits count-trailing-zeros
@@ -44,7 +44,7 @@ GNULIB_MODULES='
   nanosleep nproc nstrftime
   pathmax pipe2 pselect pthread_sigmask
   qcopy-acl readlink readlinkat regex
-  sig2str sigdescr_np socklen stat-time std-gnu11 stdalign stdbool stddef stdio
+  sig2str sigdescr_np socklen stat-time std-gnu11 stdbool stddef stdio
   stpcpy strnlen strtoimax symlink sys_stat sys_time
   tempname time time_r time_rz timegm timer-time timespec-add timespec-sub
   update-copyright unlocked-io utimensat
diff --git a/admin/notes/elpa b/admin/notes/elpa
index 1e9e7a9f52b..afcda71d1dd 100644
--- a/admin/notes/elpa
+++ b/admin/notes/elpa
@@ -3,7 +3,7 @@ NOTES ON THE EMACS PACKAGE ARCHIVE
 The GNU Emacs package archive, at elpa.gnu.org, is managed using a Git
 repository named "elpa", hosted on Savannah.  To check it out:
 
-  git clone git://git.sv.gnu.org/emacs/elpa
+  git clone https://git.savannah.gnu.org/git/emacs/elpa
   cd elpa
   make setup
 
diff --git a/admin/notes/tree-sitter/treesit_record_change 
b/admin/notes/tree-sitter/treesit_record_change
new file mode 100644
index 00000000000..bb0f9edc353
--- /dev/null
+++ b/admin/notes/tree-sitter/treesit_record_change
@@ -0,0 +1,50 @@
+NOTES ON TREESIT_RECORD_CHANGE
+
+It is vital that Emacs informs tree-sitter of every change made to the
+buffer, lest tree-sitter's parse tree would be corrupted/out of sync.
+
+All buffer changes in Emacs are made through functions in insdel.c
+(and casefiddle.c), I augmented functions in those files with calls to
+treesit_record_change.  Below is a manifest of all the relavent
+functions in insdel.c as of Emacs 29:
+
+Function                          Calls
+----------------------------------------------------------------------
+copy_text                         (*1)
+insert                            insert_1_both
+insert_and_inherit                insert_1_both
+insert_char                       insert
+insert_string                     insert
+insert_before_markers             insert_1_both
+insert_before_markers_and_inherit insert_1_both
+insert_1_both                     treesit_record_change
+insert_from_string                insert_from_string_1
+insert_from_string_before_markers insert_from_string_1
+insert_from_string_1              treesit_record_change
+insert_from_gap_1                 treesit_record_change
+insert_from_gap                   insert_from_gap_1
+insert_from_buffer                treesit_record_change
+insert_from_buffer_1              (used by insert_from_buffer) (*2)
+replace_range                     treesit_record_change
+replace_range_2                   (caller needs to call treesit_r_c)
+del_range                         del_range_1
+del_range_1                       del_range_2
+del_range_byte                    del_range_2
+del_range_both                    del_range_2
+del_range_2                       treesit_record_change
+
+(*1) This functions is used only to copy from string to string when
+used outside of insdel.c, and when used inside insdel.c, the caller
+calls treesit_record_change.
+
+(*2) This function is a static function, and insert_from_buffer is its
+only caller.  So it should be fine to call treesit_record_change in
+insert_from_buffer but not insert_from_buffer_1.  I also left a
+reminder comment.
+
+
+As for casefiddle.c, do_casify_unibyte_region and
+do_casify_multibyte_region modifies buffer, but they are static
+functions and are called by casify_region, which calls
+treesit_record_change.  Other higher-level functions calls
+casify_region to do the work.
\ No newline at end of file
diff --git a/build-aux/config.guess b/build-aux/config.guess
index 980b0208381..69188da73d7 100755
--- a/build-aux/config.guess
+++ b/build-aux/config.guess
@@ -1,10 +1,10 @@
 #! /bin/sh
 # Attempt to guess a canonical system name.
-#   Copyright 1992-2022 Free Software Foundation, Inc.
+#   Copyright 1992-2023 Free Software Foundation, Inc.
 
 # shellcheck disable=SC2006,SC2268 # see below for rationale
 
-timestamp='2022-09-17'
+timestamp='2023-01-01'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -60,7 +60,7 @@ version="\
 GNU config.guess ($timestamp)
 
 Originally written by Per Bothner.
-Copyright 1992-2022 Free Software Foundation, Inc.
+Copyright 1992-2023 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
diff --git a/build-aux/config.sub b/build-aux/config.sub
index baf1512b3c0..de4259e4047 100755
--- a/build-aux/config.sub
+++ b/build-aux/config.sub
@@ -1,10 +1,10 @@
 #! /bin/sh
 # Configuration validation subroutine script.
-#   Copyright 1992-2022 Free Software Foundation, Inc.
+#   Copyright 1992-2023 Free Software Foundation, Inc.
 
 # shellcheck disable=SC2006,SC2268 # see below for rationale
 
-timestamp='2022-09-17'
+timestamp='2023-01-21'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -76,7 +76,7 @@ Report bugs and patches to <config-patches@gnu.org>."
 version="\
 GNU config.sub ($timestamp)
 
-Copyright 1992-2022 Free Software Foundation, Inc.
+Copyright 1992-2023 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -1075,7 +1075,7 @@ case $cpu-$vendor in
        pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
                cpu=i586
                ;;
-       pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*)
+       pentiumpro-* | p6-* | 6x86-* | athlon-* | athlon_*-*)
                cpu=i686
                ;;
        pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
diff --git a/doc/emacs/basic.texi b/doc/emacs/basic.texi
index 2cc45a8805e..a271cb65bdc 100644
--- a/doc/emacs/basic.texi
+++ b/doc/emacs/basic.texi
@@ -887,19 +887,40 @@ z z z}.  The first @kbd{C-x z} repeats the command once, 
and each
 subsequent @kbd{z} repeats it once again.
 
 @findex repeat-mode
+@findex describe-repeat-maps
 @vindex repeat-exit-key
 @vindex repeat-exit-timeout
-  Also you can activate @code{repeat-mode} that temporarily enables a
-transient mode with short keys after a limited number of commands.
-Currently supported shorter key sequences are @kbd{C-x u u} instead of
-@kbd{C-x u C-x u} to undo many changes, @kbd{C-x o o} instead of
-@kbd{C-x o C-x o} to switch several windows, @kbd{C-x @{ @{ @} @} ^ ^
-v v} to resize the selected window interactively, @kbd{M-g n n p p} to
-navigate @code{next-error} matches, and @kbd{C-x ] ] [ [} to navigate
-through pages.  Any other key exits transient mode and then is
-executed normally.  The user option @code{repeat-exit-key} defines an
-additional key to exit this transient mode.  Also it's possible to
-break the repetition chain automatically after some idle time by
-customizing the user option @code{repeat-exit-timeout} to specify the
-idle time in seconds after which this transient mode will be turned
-off.
+  You can also activate @code{repeat-mode} which allows repeating
+commands bound to sequences of two or more keys by typing a single
+character.  For example, after typing @w{@kbd{C-x u}} (@code{undo},
+@pxref{Undo}) to undo the most recent edits, you can undo many more
+edits by typing @w{@kbd{u u u@dots{}}}.  Similarly, type @w{@kbd{C-x o
+o o@dots{}}} instead of @w{@kbd{C-x o C-x o C-x o@dots{}}} to switch
+to the window several windows away.  This works by entering a
+transient repeating mode after you type the full key sequence that
+invokes the command; the single-key shortcuts are shown in the echo
+area.
+
+Only some commands support repetition in @code{repeat-mode}; type
+@w{@kbd{M-x describe-repeat-maps @key{RET}}} to see which ones.
+
+The single-character shortcuts enabled by the transient repeating mode
+do not need to be identical: for example, after typing @w{@kbd{C-x
+@{}}, either @kbd{@{} or @kbd{@}} or @kbd{^} or @kbd{v}, or any series
+that mixes these characters in any order, will resize the selected
+window in respective ways.  Similarly, after @w{@kbd{M-g n}} or
+@kbd{M-g p}, typing any sequence of @kbd{n} and/or @kbd{p} in any mix
+will repeat @code{next-error} and @code{previous-error} to navigate in
+a @file{*compilation*} or @file{*grep*} buffer (@pxref{Compilation
+Mode}).
+
+Typing any key other than those defined to repeat the previous command
+exits the transient repeating mode, and then the key you typed is
+executed normally.  You can also define a key which will exit the
+transient repeating mode @emph{without} executing the key which caused
+the exit.  To this end, customize the user option
+@code{repeat-exit-key} to name a key; one natural value is @key{RET}.
+Finally, it's possible to break the repetition chain automatically
+after some amount of idle time: customize the user option
+@code{repeat-exit-timeout} to specify the idle time in seconds after
+which this transient repetition mode will be turned off automatically.
diff --git a/doc/emacs/building.texi b/doc/emacs/building.texi
index 98f67ddd9d9..3f6a418de1a 100644
--- a/doc/emacs/building.texi
+++ b/doc/emacs/building.texi
@@ -961,9 +961,7 @@ the fringe of a source buffer to set a breakpoint there.
 @vindex gud-gdb-command-name
   To run GDB using just the GUD interaction buffer interface, without
 these additional features, use @kbd{M-x gud-gdb} (@pxref{Starting
-GUD}).  You must use this if you want to debug multiple programs
-within one Emacs session, as that is currently unsupported by @kbd{M-x
-gdb}.
+GUD}).
 
   Internally, @kbd{M-x gdb} informs GDB that its screen size is
 unlimited; for correct operation, you must not change GDB's screen
@@ -1051,9 +1049,9 @@ to restore only when @code{gdb-show-main} is 
non-@code{nil}.
   You may also specify additional GDB-related buffers to display,
 either in the same frame or a different one.  Select the buffers you
 want by typing @kbd{M-x gdb-display-@var{buffertype}-buffer} or
-@kbd{M-x gdb-frame-@var{buffertype}-buffer}, where @var{buffertype}
-is the relevant buffer type, such as @samp{breakpoints}.  You can do
-the same with the menu bar, with the @samp{GDB-Windows} and
+@kbd{M-x gdb-frame-@var{buffertype}-buffer}, where @var{buffertype} is
+the relevant buffer type, such as @samp{breakpoints} or @samp{io}.
+You can do the same from the menu bar, with the @samp{GDB-Windows} and
 @samp{GDB-Frames} sub-menus of the @samp{GUD} menu.
 
 @vindex gdb-max-source-window-count
@@ -1273,10 +1271,14 @@ non-@code{nil} value.
 @node Other GDB Buffers
 @subsubsection Other GDB Buffers
 
+Other buffers provided by @kbd{M-x gdb} whose display you can
+optionally request include:
+
 @table @asis
+@findex gdb-display-locals-buffer
 @item Locals Buffer
 This buffer displays the values of local variables of the current
-frame for simple data types (@pxref{Frame Info, Frame Info,
+stack frame for simple data types (@pxref{Frame Info, Frame Info,
 Information on a frame, gdb, The GNU debugger}).  Press @key{RET} or
 click @kbd{mouse-2} on the value if you want to edit it.
 
@@ -1286,20 +1288,35 @@ you can examine the value of the local variable at 
point by typing
 GDB, use @key{RET} or @kbd{mouse-2} on the type description
 (@samp{[struct/union]} or @samp{[array]}).  @xref{Watch Expressions}.
 
+To display the Locals buffer, type @kbd{M-x gdb-display-locals-buffer}.
+
+@findex gdb-display-io-buffer
+@item I/O Buffer
+If the program you are debugging uses standard input and output
+streams for interaction with the user, or emits a significant amount
+of output to its standard output, you may wish to separate its I/O
+from interaction with GDB.  Use the command @w{@kbd{M-x
+gdb-display-io-buffer}} to show a window with a buffer to which Emacs
+redirects the input and output from the program you are debugging.
+
+@findex gdb-display-registers-buffer
 @item Registers Buffer
-@findex toggle-gdb-all-registers
 This buffer displays the values held by the registers
-(@pxref{Registers,,, gdb, The GNU debugger}).  Press @key{RET} or
-click @kbd{mouse-2} on a register if you want to edit its value.  With
-GDB 6.4 or later, recently changed register values display with
-@code{font-lock-warning-face}.
+(@pxref{Registers,,, gdb, The GNU debugger}).  Request the display of
+this buffer with the command @kbd{M-x gdb-display-registers-buffer}.
+Press @key{RET} or click @kbd{mouse-2} on a register if you want to
+edit its value.  With GDB 6.4 or later, recently changed register
+values display with @code{font-lock-warning-face}.
 
+@findex gdb-display-disassembly-buffer
 @item Assembler Buffer
 The assembler buffer displays the current frame as machine code.  An
 arrow points to the current instruction, and you can set and remove
 breakpoints as in a source buffer.  Breakpoint icons also appear in
-the fringe or margin.
+the fringe or margin.  To request the display of this buffer, use
+@kbd{M-x gdb-display-disassembly-buffer}.
 
+@findex gdb-display-memory-buffer
 @item Memory Buffer
 The memory buffer lets you examine sections of program memory
 (@pxref{Memory, Memory, Examining memory, gdb, The GNU debugger}).
@@ -1307,7 +1324,8 @@ Click @kbd{mouse-1} on the appropriate part of the header 
line to
 change the starting address or number of data items that the buffer
 displays.  Alternatively, use @kbd{S} or @kbd{N} respectively.  Click
 @kbd{mouse-3} on the header line to select the display format or unit
-size for these data items.
+size for these data items.  Use @w{@kbd{M-x
+gdb-display-memory-buffer}} to request display of this buffer.
 @end table
 
 When @code{gdb-many-windows} is non-@code{nil}, the locals buffer
diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi
index f77ab569483..97732b65e32 100644
--- a/doc/emacs/display.texi
+++ b/doc/emacs/display.texi
@@ -1024,17 +1024,65 @@ customize-group @key{RET} font-lock-faces @key{RET}}.  
You can then
 use that customization buffer to customize the appearance of these
 faces.  @xref{Face Customization}.
 
+@cindex just-in-time (JIT) font-lock
+@cindex background syntax highlighting
+  Fontifying very large buffers can take a long time.  To avoid large
+delays when a file is visited, Emacs initially fontifies only the
+visible portion of a buffer.  As you scroll through the buffer, each
+portion that becomes visible is fontified as soon as it is displayed;
+this type of Font Lock is called @dfn{Just-In-Time} (or @dfn{JIT})
+Lock.  You can control how JIT Lock behaves, including telling it to
+perform fontification while idle, by customizing variables in the
+customization group @samp{jit-lock}.  @xref{Specific Customization}.
+
+  The information that major modes use for determining which parts of
+buffer text to fontify and what faces to use can be based on several
+different ways of analyzing the text:
+
+@itemize @bullet
+@item
+Search for keywords and other textual patterns based on regular
+expressions (@pxref{Regexp Search,, Regular Expression Search}).
+
+@item
+Find syntactically distinct parts of text based on built-in syntax
+tables (@pxref{Syntax Tables,,, elisp, The Emacs Lisp Reference
+Manual}).
+
+@item
+Use syntax tree produced by a full-blown parser, via a special-purpose
+library, such as the tree-sitter library (@pxref{Parsing Program
+Source,,, elisp, The Emacs Lisp Reference Manual}), or an external
+program.
+@end itemize
+
+@menu
+* Traditional Font Lock::  Font Lock based on regexps and syntax tables.
+* Parser-based Font Lock:: Font Lock based on external parser.
+@end menu
+
+@node Traditional Font Lock
+@subsection Traditional Font Lock
+@cindex traditional font-lock
+
+  ``Traditional'' methods of providing font-lock information are based
+on regular-expression search and on syntactic analysis using syntax
+tables built into Emacs.  This subsection describes the use and
+customization of font-lock for major modes which use these traditional
+methods.
+
 @vindex font-lock-maximum-decoration
-  You can customize the variable @code{font-lock-maximum-decoration}
-to alter the amount of fontification applied by Font Lock mode, for
-major modes that support this feature.  The value should be a number
-(with 1 representing a minimal amount of fontification; some modes
-support levels as high as 3); or @code{t}, meaning ``as high as
-possible'' (the default).  To be effective for a given file buffer,
-the customization of @code{font-lock-maximum-decoration} should be
-done @emph{before} the file is visited; if you already have the file
-visited in a buffer when you customize this variable, kill the buffer
-and visit the file again after the customization.
+  You can control the amount of fontification applied by Font Lock
+mode by customizing the variable @code{font-lock-maximum-decoration},
+for major modes that support this feature.  The value of this variable
+should be a number (with 1 representing a minimal amount of
+fontification; some modes support levels as high as 3); or @code{t},
+meaning ``as high as possible'' (the default).  To be effective for a
+given file buffer, the customization of
+@code{font-lock-maximum-decoration} should be done @emph{before} the
+file is visited; if you already have the file visited in a buffer when
+you customize this variable, kill the buffer and visit the file again
+after the customization.
 
 You can also specify different numbers for particular major modes; for
 example, to use level 1 for C/C++ modes, and the default level
@@ -1082,16 +1130,59 @@ keywords by customizing the @code{font-lock-ignore} 
option,
 @pxref{Customizing Keywords,,, elisp, The Emacs Lisp Reference
 Manual}.
 
-@cindex just-in-time (JIT) font-lock
-@cindex background syntax highlighting
-  Fontifying large buffers can take a long time.  To avoid large
-delays when a file is visited, Emacs initially fontifies only the
-visible portion of a buffer.  As you scroll through the buffer, each
-portion that becomes visible is fontified as soon as it is displayed;
-this type of Font Lock is called @dfn{Just-In-Time} (or @dfn{JIT})
-Lock.  You can control how JIT Lock behaves, including telling it to
-perform fontification while idle, by customizing variables in the
-customization group @samp{jit-lock}.  @xref{Specific Customization}.
+@node Parser-based Font Lock
+@subsection Parser-based Font Lock
+@cindex font-lock via tree-sitter
+@cindex parser-based font-lock
+  If your Emacs was built with the tree-sitter library, it can use the
+results of parsing the buffer text by that library for the purposes of
+fontification.  This is usually faster and more accurate than the
+``traditional'' methods described in the previous subsection, since
+the tree-sitter library provides full-blown parsers for programming
+languages and other kinds of formatted text which it supports.  Major
+modes which utilize the tree-sitter library are named
+@code{@var{foo}-ts-mode}, with the @samp{-ts-} part indicating the use
+of the library.  This subsection documents the Font Lock support based
+on the tree-sitter library.
+
+@vindex treesit-font-lock-level
+  You can control the amount of fontification applied by Font Lock
+mode of major modes based on tree-sitter by customizing the variable
+@code{treesit-font-lock-level}.  Its value is a number between 1 and
+4:
+
+@table @asis
+@item Level 1
+This level usually fontifies only comments and function names in
+function definitions.
+@item Level 2
+This level adds fontification of keywords, strings, and data types.
+@item Level 3
+This is the default level; it adds fontification of assignments,
+numbers, properties, etc.
+@item Level 4
+This level adds everything else that can be fontified: operators,
+delimiters, brackets, other punctuation, function names in function
+calls, variables, etc.
+@end table
+
+@vindex treesit-font-lock-feature-list
+@noindent
+What exactly constitutes each of the syntactical categories mentioned
+above depends on the major mode and the parser grammar used by
+tree-sitter for the major-mode's language.  However, in general the
+categories follow the conventions of the programming language or the
+file format supported by the major mode.  The buffer-local value of
+the variable @code{treesit-font-lock-feature-list} holds the
+fontification features supported by a tree-sitter based major mode,
+where each sub-list shows the features provided by the corresponding
+fontification level.
+
+  Once you change the value of @code{treesit-font-lock-level} via
+@w{@kbd{M-x customize-variable}} (@pxref{Specific Customization}), it
+takes effect immediately in all the existing buffers and for files you
+visit in the future in the same session.
+
 
 @node Highlight Interactively
 @section Interactive Highlighting
diff --git a/doc/emacs/emacs.texi b/doc/emacs/emacs.texi
index b6d149eb3ef..7071ea44edd 100644
--- a/doc/emacs/emacs.texi
+++ b/doc/emacs/emacs.texi
@@ -383,6 +383,10 @@ Controlling the Display
 * Visual Line Mode::       Word wrap and screen line-based editing.
 * Display Custom::         Information on variables for customizing display.
 
+Font Lock
+* Traditional Font Lock::  Font Lock based on regexps and syntax tables.
+* Parser-based Font Lock:: Font Lock based on external parser.
+
 Searching and Replacement
 
 * Incremental Search::     Search happens as you type the string.
diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi
index 42e252c417b..664b9d5d9a3 100644
--- a/doc/emacs/files.texi
+++ b/doc/emacs/files.texi
@@ -215,6 +215,17 @@ by the integers that Emacs can represent 
(@pxref{Buffers}).  If you
 try, Emacs displays an error message saying that the maximum buffer
 size has been exceeded.
 
+@vindex treesit-max-buffer-size
+  If you try to visit a file whose major mode (@pxref{Major Modes})
+uses the tree-sitter parsing library, Emacs will display a warning if
+the file's size in bytes is larger than the value of the variable
+@code{treesit-max-buffer-size}.  The default value is 40 megabytes for
+64-bit Emacs and 15 megabytes for 32-bit Emacs.  This avoids the
+danger of having Emacs run out of memory by preventing the activation
+of major modes based on tree-sitter in such large buffers, because a
+typical tree-sitter parser needs about 10 times as much memory as the
+text it parses.
+
 @cindex wildcard characters in file names
 @vindex find-file-wildcards
   If the file name you specify contains shell-style wildcard
diff --git a/doc/emacs/frames.texi b/doc/emacs/frames.texi
index 3ee6eb59dbb..ce631561be7 100644
--- a/doc/emacs/frames.texi
+++ b/doc/emacs/frames.texi
@@ -334,6 +334,7 @@ In this way, you can use the mouse to move point over a 
button without
 activating it.  Dragging the mouse over or onto a button has its usual
 behavior of setting the region, and does not activate the button.
 
+@vindex mouse-1-click-follows-link
   You can change how @kbd{mouse-1} applies to buttons by customizing
 the variable @code{mouse-1-click-follows-link}.  If the value is a
 positive integer, that determines how long you need to hold the mouse
diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi
index 88d4188d144..a5e1689b6c7 100644
--- a/doc/emacs/misc.texi
+++ b/doc/emacs/misc.texi
@@ -470,11 +470,7 @@ documents.  It provides features such as slicing, zooming, 
and
 searching inside documents.  It works by converting the document to a
 set of images using the @command{gs} (GhostScript) or
 @command{pdfdraw}/@command{mutool draw} (MuPDF) commands and other
-external tools @footnote{PostScript files require GhostScript, DVI
-files require @code{dvipdf} or @code{dvipdfm}, OpenDocument and
-Microsoft Office documents require the @code{unoconv} tool, and EPUB,
-CBZ, FB2, XPS and OXPS files require @code{mutool} to be available.},
-and displaying those images.
+external tools, and then displays those converted images.
 
 @findex doc-view-toggle-display
 @findex doc-view-minor-mode
@@ -751,6 +747,8 @@ Command Output*"} (@code{shell-command-buffer-name}) buffer 
(if the
 output is long).  The variables @code{resize-mini-windows} and
 @code{max-mini-window-height} (@pxref{Minibuffer Edit}) control when
 Emacs should consider the output to be too long for the echo area.
+Note that customizing @code{shell-command-dont-erase-buffer},
+described below, can affect what is displayed in the echo area.
 
   For instance, one way to decompress a file named @file{foo.gz} is to
 type @kbd{M-! gunzip foo.gz @key{RET}}.  That shell command normally
@@ -867,6 +865,10 @@ Restores the position of point as it was before inserting 
the
 shell-command output.
 @end table
 
+Note that if this option is non-@code{nil}, the output shown in the
+echo area could be from more than just the last command, since the
+echo area just displays a portion of the output buffer.
+
 In case the output buffer is not the current buffer, shell command
 output is appended at the end of this buffer.
 
diff --git a/doc/emacs/programs.texi b/doc/emacs/programs.texi
index 065ed1c51f7..d983c2b59c6 100644
--- a/doc/emacs/programs.texi
+++ b/doc/emacs/programs.texi
@@ -255,6 +255,17 @@ they do their standard jobs in a way better fitting a 
particular
 language.  Other major modes may replace any or all of these key
 bindings for that purpose.
 
+@cindex nested defuns
+@vindex treesit-defun-tactic
+  Some programming languages supported @dfn{nested defuns}, whereby a
+defun (such as a function or a method or a class) can be defined
+inside (i.e., as part of the body) of another defun.  The commands
+described above by default find the beginning and the end of the
+@emph{innermost} defun around point.  Major modes based on the
+tree-sitter library provide control of this behavior: if the variable
+@code{treesit-defun-tactic} is set to the value @code{top-level}, the
+defun commands will find the @emph{outermost} defuns instead.
+
 @node Moving by Sentences
 @subsection Moving by Sentences
 @cindex sentences, in programming languages
@@ -599,15 +610,19 @@ then indent it like this:
 @item C-c C-q
 @kindex C-c C-q @r{(C mode)}
 @findex c-indent-defun
+@findex c-ts-mode-indent-defun
 Reindent the current top-level function definition or aggregate type
-declaration (@code{c-indent-defun}).
+declaration (@code{c-indent-defun} in CC mode,
+@code{c-ts-mode-indent-defun} in @code{c-ts-mode} based on tree-sitter).
 
 @item C-M-q
 @kindex C-M-q @r{(C mode)}
 @findex c-indent-exp
-Reindent each line in the balanced expression that follows point
-(@code{c-indent-exp}).  A prefix argument inhibits warning messages
-about invalid syntax.
+@findex prog-indent-sexp
+Reindent each line in the balanced expression that follows point.  In
+CC mode, this invokes @code{c-indent-exp}; in tree-sitter based
+@code{c-ts-mode} this invokes a more general @code{prog-indent-sexp}.
+A prefix argument inhibits warning messages about invalid syntax.
 
 @item @key{TAB}
 @findex c-indent-line-or-region
@@ -647,7 +662,8 @@ onto the indentation of the @dfn{anchor statement}.
 
 @table @kbd
 @item C-c . @var{style} @key{RET}
-Select a predefined style @var{style} (@code{c-set-style}).
+Select a predefined style @var{style} (@code{c-set-style} in CC mode,
+@code{c-ts-mode-set-style} in @code{c-ts-mode} based on tree-sitter).
 @end table
 
   A @dfn{style} is a named collection of customizations that can be
@@ -663,6 +679,7 @@ typing @kbd{C-M-q} at the start of a function definition.
 
 @kindex C-c . @r{(C mode)}
 @findex c-set-style
+@findex c-ts-mode-set-style
   To choose a style for the current buffer, use the command @w{@kbd{C-c
 .}}.  Specify a style name as an argument (case is not significant).
 This command affects the current buffer only, and it affects only
@@ -671,11 +688,11 @@ the code already in the buffer.  To reindent the whole 
buffer in the
 new style, you can type @kbd{C-x h C-M-\}.
 
 @vindex c-default-style
-  You can also set the variable @code{c-default-style} to specify the
-default style for various major modes.  Its value should be either the
-style's name (a string) or an alist, in which each element specifies
-one major mode and which indentation style to use for it.  For
-example,
+  When using CC mode, you can also set the variable
+@code{c-default-style} to specify the default style for various major
+modes.  Its value should be either the style's name (a string) or an
+alist, in which each element specifies one major mode and which
+indentation style to use for it.  For example,
 
 @example
 (setq c-default-style
@@ -692,6 +709,11 @@ one of the C-like major modes; thus, if you specify a new 
default
 style for Java mode, you can make it take effect in an existing Java
 mode buffer by typing @kbd{M-x java-mode} there.
 
+@vindex c-ts-mode-indent-style
+  When using the tree-sitter based @code{c-ts-mode}, you can set the
+default indentation style by customizing the variable
+@code{c-ts-mode-indent-style}.
+
   The @code{gnu} style specifies the formatting recommended by the GNU
 Project for C; it is the default, so as to encourage use of our
 recommended style.
diff --git a/doc/emacs/text.texi b/doc/emacs/text.texi
index 78e89d8031a..18f2274cfa6 100644
--- a/doc/emacs/text.texi
+++ b/doc/emacs/text.texi
@@ -1021,14 +1021,16 @@ this variable is @code{insert}, the buttons are 
inserted directly into
 the buffer text, so @key{RET} on the button will also toggle display
 of the section, like a mouse click does.  If the value is
 @code{in-margins}, Outline minor mode will use the window margins to
-indicate that a section is hidden.
+indicate that a section is hidden.  The buttons are customizable as icons
+(@pxref{Icons}).
 
 @vindex outline-minor-mode-cycle
   If the @code{outline-minor-mode-cycle} user option is
-non-@code{nil}, the @kbd{TAB} and @kbd{S-@key{TAB}} keys are enabled on the
-outline heading lines.  @kbd{TAB} cycles hiding, showing the
-sub-heading, and showing all for the current section.  @kbd{S-@key{TAB}}
-does the same for the entire buffer.
+non-@code{nil}, the @kbd{TAB} and @kbd{S-@key{TAB}} keys that cycle
+the visibility are enabled on the outline heading lines
+(@pxref{Outline Visibility, outline-cycle}).  @kbd{TAB} cycles hiding,
+showing the sub-heading, and showing all for the current section.
+@kbd{S-@key{TAB}} does the same for the entire buffer.
 
 @node Outline Format
 @subsection Format of Outlines
diff --git a/doc/lispref/internals.texi b/doc/lispref/internals.texi
index e1a4613875c..deb1021283f 100644
--- a/doc/lispref/internals.texi
+++ b/doc/lispref/internals.texi
@@ -732,14 +732,15 @@ Emacs session.
 @section C Dialect
 @cindex C programming language
 
-The C part of Emacs is portable to C99 or later: C11-specific features such
-as @samp{<stdalign.h>} and @samp{_Noreturn} are not used without a check,
+The C part of Emacs is portable to C99 or later: later C features such
+as @samp{<stdckdint.h>} and @samp{[[noreturn]]} are not used without a check,
 typically at configuration time, and the Emacs build procedure
-provides a substitute implementation if necessary.  Some C11 features,
+provides a substitute implementation if necessary.  Some later features,
 such as anonymous structures and unions, are too difficult to emulate,
 so they are avoided entirely.
 
-At some point in the future the base C dialect will no doubt change to C11.
+At some point in the future the base C dialect will no doubt change to
+something later than C99.
 
 @node Writing Emacs Primitives
 @section Writing Emacs Primitives
@@ -894,15 +895,17 @@ Currently, only the following attributes are recognized:
 @table @code
 @item noreturn
 Declares the C function as one that never returns.  This corresponds
-to the C11 keyword @code{_Noreturn} and to @w{@code{__attribute__
-((__noreturn__))}} attribute of GCC (@pxref{Function Attributes,,,
-gcc, Using the GNU Compiler Collection}).
+to C23's @code{[[noreturn]]}, to C11's @code{_Noreturn}, and to GCC's
+@w{@code{__attribute__ ((__noreturn__))}} (@pxref{Function
+Attributes,,, gcc, Using the GNU Compiler Collection}).  (Internally,
+Emacs's own C code uses @code{_Noreturn} as it can be defined as a
+macro on C platforms that do not support it.)
 
 @item const
 Declares that the function does not examine any values except its
 arguments, and has no effects except the return value.  This
-corresponds to @w{@code{__attribute__ ((__const__))}} attribute of
-GCC.
+corresponds to C23's @code{[[unsequenced]]} and to GCC's
+@w{@code{__attribute__ ((__const__))}}.
 
 @item noinline
 This corresponds to @w{@code{__attribute__ ((__noinline__))}}
diff --git a/doc/lispref/variables.texi b/doc/lispref/variables.texi
index 39d0906f6c4..5584cbce9a6 100644
--- a/doc/lispref/variables.texi
+++ b/doc/lispref/variables.texi
@@ -2023,6 +2023,7 @@ file-local variables stored in 
@code{file-local-variables-alist}.
 @end defvar
 
 @cindex safe local variable
+@cindex @code{safe-local-variable}, property of variable
   You can specify safe values for a variable with a
 @code{safe-local-variable} property.  The property has to be a
 function of one argument; any value is safe if the function returns
diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi
index 57a2020fdca..e51e2cf799b 100644
--- a/doc/misc/eshell.texi
+++ b/doc/misc/eshell.texi
@@ -1059,7 +1059,9 @@ remote connection.
 This refers to the last argument of the last command.  With a
 subscript, you can access any argument of the last command.  For
 example, @samp{$_[1]} refers to the second argument of the last
-command (excluding the command name itself).
+command (excluding the command name itself).  To get all arguments of
+the last command, you can use an index range like @samp{$_[..]}
+(@pxref{Dollars Expansion}).
 
 @vindex $$
 @item $$
@@ -1370,11 +1372,24 @@ index.  The exact behavior depends on the type of 
@var{expr}'s value:
 @item a sequence
 Expands to the element at the (zero-based) index @var{i} of the
 sequence (@pxref{Sequences Arrays Vectors, Sequences, , elisp, The
-Emacs Lisp Reference Manual}).
+Emacs Lisp Reference Manual}).  If @var{i} is negative, @var{i} counts
+from the end, so -1 refers to the last element of the sequence.
+
+If @var{i} is a range like @code{@var{start}..@var{end}}, this expands
+to a subsequence from the indices @var{start} to @var{end}, where
+@var{end} is excluded@footnote{This behavior is different from ranges
+in Bash (where both the start and end are included in the range), but
+matches the behavior of similar Emacs Lisp functions, like
+@code{substring} (@pxref{Creating Strings, , , elisp, The Emacs Lisp
+Reference Manual}).}.  @var{start} and/or @var{end} can also be
+omitted, which is equivalent to the start and/or end of the entire
+list.  For example, @samp{$@var{expr}[-2..]} expands to the last two
+values of @var{expr}.
 
 @item a string
 Split the string at whitespace, and then expand to the @var{i}th
-element of the resulting sequence.
+element of the resulting sequence.  As above, @var{i} can be a range
+like @code{@var{start}..@var{end}}.
 
 @item an alist
 If @var{i} is a non-numeric value, expand to the value associated with
@@ -2442,13 +2457,6 @@ current being used.
 
 This way, the user could change it to use rc syntax: @samp{>[2=1]}.
 
-@item Allow @samp{$_[-1]}, which would indicate the last element of the array
-
-@item Make @samp{$x[*]} equal to listing out the full contents of @samp{x}
-
-Return them as a list, so that @samp{$_[*]} is all the arguments of the
-last command.
-
 @item Copy ANSI code handling from @file{term.el} into @file{em-term.el}
 
 Make it possible for the user to send char-by-char to the underlying
diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi
index a8a59f982fc..d344feb2d63 100644
--- a/doc/misc/tramp.texi
+++ b/doc/misc/tramp.texi
@@ -361,7 +361,7 @@ Another way is to follow the terminal session below:
 @example
 @group
 $ cd ~/emacs
-$ git clone git://git.savannah.gnu.org/tramp.git
+$ git clone https://git.savannah.gnu.org/git/tramp.git
 @end group
 @end example
 
diff --git a/doc/misc/transient.texi b/doc/misc/transient.texi
index 62ab0ff3fcf..8ac5df9904c 100644
--- a/doc/misc/transient.texi
+++ b/doc/misc/transient.texi
@@ -64,6 +64,15 @@ reading a new value in the minibuffer.
 Calling a suffix command usually causes the transient to be exited
 but suffix commands can also be configured to not exit the transient.
 
+@quotation
+The second part of this manual, which describes how to modify existing
+transients and create new transients from scratch, can be hard to
+digest if you are just getting started.  A useful resource to get over
+that hurdle is Psionic K's interactive tutorial, available at
+@uref{https://github.com/positron-solutions/transient-showcase}.
+
+@end quotation
+
 @noindent
 This manual is for Transient version 0.3.7.50.
 
@@ -893,7 +902,16 @@ same customization.
 
 To an extent, transients can be customized interactively, see
 @ref{Enabling and Disabling Suffixes}.  This section explains how existing
-transients can be further modified non-interactively.
+transients can be further modified non-interactively.  Let's begin
+with an example:
+
+@lisp
+(transient-append-suffix 'magit-patch-apply "-3"
+  '("-R" "Apply in reverse" "--reverse"))
+@end lisp
+
+This inserts a new infix argument to toggle the @code{--reverse} argument
+after the infix argument that toggles @code{-3} in @code{magit-patch-apply}.
 
 The following functions share a few arguments:
 
diff --git a/etc/NEWS b/etc/NEWS
index 5b8ab06086c..e0175bacfdf 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -149,6 +149,13 @@ of arguments into a command, such as when defining 
aliases.  For more
 information, see the "(eshell) Dollars Expansion" node in the Eshell
 manual.
 
++++
+*** Eshell now supports negative numbers and ranges for indices.
+Now, you can retrieve the last element of a list with '$my-list[-1]'
+or get a sublist of elements 2 through 4 with '$my-list[2..5]'.  For
+more information, see the "(eshell) Dollars Expansion" node in the
+Eshell manual.
+
 ---
 *** Eshell now uses 'field' properties in its output.
 In particular, this means that pressing the '<home>' key moves the
diff --git a/etc/NEWS.29 b/etc/NEWS.29
index 4d199676848..e3cbeb84d30 100644
--- a/etc/NEWS.29
+++ b/etc/NEWS.29
@@ -563,6 +563,20 @@ The variable 'font-lock-support-mode' is occasionally 
useful for
 debugging purposes.  It is now a regular variable (instead of a user
 option) and can be set to nil to disable Just-in-time Lock mode.
 
++++
+** The 'utf-8-auto' coding-system now produces BOM on encoding.
+This is actually a bugfix, since this is how 'utf-8-auto' was
+documented from day one; it just didn't behave according to
+documentation.  It turns out some Lisp programs were using this
+coding-system on the wrong assumption that the "auto" part means some
+automagic handling of the end-of-line (EOL) format conversion; those
+program will now start to fail, because BOM signature in UTF-8 encoded
+text is rarely expected.  That is the reason we mention this bugfix
+here.
+
+In general, this coding-system should probably never be used for
+encoding, only for decoding.
+
 
 * Changes in Emacs 29.1
 
@@ -1018,6 +1032,8 @@ quotes removed.
 
 ---
 *** 'M-x apropos-variable' output now includes values of variables.
+Such apropos buffer is more easily viewed with outlining after
+enabling 'outline-minor-mode' in 'apropos-mode'.
 
 +++
 *** New docstring syntax to indicate that symbols shouldn't be links.
@@ -1337,6 +1353,18 @@ dragged.
 Customize this option to limit the number of entries in the menu
 "Edit → Paste from Kill Menu".  The default is 60.
 
+---
+** New user option 'copy-region-blink-predicate'.
+By default, when copying a region with 'kill-ring-save', Emacs only
+blinks point and mark when the region is not denoted visually, that
+is, when either the region is inactive, or the 'region' face is
+indistinguishable from the 'default' face.
+
+Users who would rather enable blinking unconditionally can now set
+this user option to 'always'.  To disable blinking unconditionally,
+either set this option to 'ignore', or set 'copy-region-blink-delay'
+to 0.
+
 +++
 ** Performing a pinch gesture on a touchpad now increases the text scale.
 
@@ -2480,6 +2508,10 @@ matches.
 ---
 *** New function 'xref-show-xrefs'.
 
+*** 'outline-minor-mode' is supported in Xref buffers.
+You can enable outlining by adding 'outline-minor-mode' to
+'xref-after-update-hook'.
+
 ** File Notifications
 
 +++
diff --git a/lib/_Noreturn.h b/lib/_Noreturn.h
index fa15b1b25e8..6ecea98b54a 100644
--- a/lib/_Noreturn.h
+++ b/lib/_Noreturn.h
@@ -26,6 +26,11 @@
        AIX system header files and several gnulib header files use precisely
        this syntax with 'extern'.  */
 #  define _Noreturn [[noreturn]]
+# elif (defined __clang__ && __clang_major__ < 16 \
+        && defined _GL_WORK_AROUND_LLVM_BUG_59792)
+   /* Compile with -D_GL_WORK_AROUND_LLVM_BUG_59792 to work around
+      that rare LLVM bug, though you may get many false-alarm warnings.  */
+#  define _Noreturn
 # elif ((!defined __cplusplus || defined __clang__) \
         && (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) \
             || (!defined __STRICT_ANSI__ \
diff --git a/lib/cdefs.h b/lib/cdefs.h
index 09a3d19b23b..412f036ce35 100644
--- a/lib/cdefs.h
+++ b/lib/cdefs.h
@@ -140,32 +140,37 @@
 #endif
 
 
+/* Gnulib avoids these definitions, as they don't work on non-glibc platforms.
+   In particular, __bos and __bos0 are defined differently in the Android libc.
+ */
+#ifndef __GNULIB_CDEFS
+
 /* Fortify support.  */
-#define __bos(ptr) __builtin_object_size (ptr, __USE_FORTIFY_LEVEL > 1)
-#define __bos0(ptr) __builtin_object_size (ptr, 0)
+# define __bos(ptr) __builtin_object_size (ptr, __USE_FORTIFY_LEVEL > 1)
+# define __bos0(ptr) __builtin_object_size (ptr, 0)
 
 /* Use __builtin_dynamic_object_size at _FORTIFY_SOURCE=3 when available.  */
-#if __USE_FORTIFY_LEVEL == 3 && (__glibc_clang_prereq (9, 0)                 \
-                                || __GNUC_PREREQ (12, 0))
-# define __glibc_objsize0(__o) __builtin_dynamic_object_size (__o, 0)
-# define __glibc_objsize(__o) __builtin_dynamic_object_size (__o, 1)
-#else
-# define __glibc_objsize0(__o) __bos0 (__o)
-# define __glibc_objsize(__o) __bos (__o)
-#endif
+# if __USE_FORTIFY_LEVEL == 3 && (__glibc_clang_prereq (9, 0)                \
+                                 || __GNUC_PREREQ (12, 0))
+#  define __glibc_objsize0(__o) __builtin_dynamic_object_size (__o, 0)
+#  define __glibc_objsize(__o) __builtin_dynamic_object_size (__o, 1)
+# else
+#  define __glibc_objsize0(__o) __bos0 (__o)
+#  define __glibc_objsize(__o) __bos (__o)
+# endif
 
 /* Compile time conditions to choose between the regular, _chk and _chk_warn
    variants.  These conditions should get evaluated to constant and optimized
    away.  */
 
-#define __glibc_safe_len_cond(__l, __s, __osz) ((__l) <= (__osz) / (__s))
-#define __glibc_unsigned_or_positive(__l) \
+# define __glibc_safe_len_cond(__l, __s, __osz) ((__l) <= (__osz) / (__s))
+# define __glibc_unsigned_or_positive(__l) \
   ((__typeof (__l)) 0 < (__typeof (__l)) -1                                  \
    || (__builtin_constant_p (__l) && (__l) > 0))
 
 /* Length is known to be safe at compile time if the __L * __S <= __OBJSZ
    condition can be folded to a constant and if it is true, or unknown (-1) */
-#define __glibc_safe_or_unknown_len(__l, __s, __osz) \
+# define __glibc_safe_or_unknown_len(__l, __s, __osz) \
   ((__osz) == (__SIZE_TYPE__) -1                                             \
    || (__glibc_unsigned_or_positive (__l)                                    \
        && __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), \
@@ -175,7 +180,7 @@
 /* Conversely, we know at compile time that the length is unsafe if the
    __L * __S <= __OBJSZ condition can be folded to a constant and if it is
    false.  */
-#define __glibc_unsafe_len(__l, __s, __osz) \
+# define __glibc_unsafe_len(__l, __s, __osz) \
   (__glibc_unsigned_or_positive (__l)                                        \
    && __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l),     \
                                                   __s, __osz))               \
@@ -184,7 +189,7 @@
 /* Fortify function f.  __f_alias, __f_chk and __f_chk_warn must be
    declared.  */
 
-#define __glibc_fortify(f, __l, __s, __osz, ...) \
+# define __glibc_fortify(f, __l, __s, __osz, ...) \
   (__glibc_safe_or_unknown_len (__l, __s, __osz)                             \
    ? __ ## f ## _alias (__VA_ARGS__)                                         \
    : (__glibc_unsafe_len (__l, __s, __osz)                                   \
@@ -194,13 +199,16 @@
 /* Fortify function f, where object size argument passed to f is the number of
    elements and not total size.  */
 
-#define __glibc_fortify_n(f, __l, __s, __osz, ...) \
+# define __glibc_fortify_n(f, __l, __s, __osz, ...) \
   (__glibc_safe_or_unknown_len (__l, __s, __osz)                             \
    ? __ ## f ## _alias (__VA_ARGS__)                                         \
    : (__glibc_unsafe_len (__l, __s, __osz)                                   \
       ? __ ## f ## _chk_warn (__VA_ARGS__, (__osz) / (__s))                  \
       : __ ## f ## _chk (__VA_ARGS__, (__osz) / (__s))))                     \
 
+#endif
+
+
 #if __GNUC_PREREQ (4,3)
 # define __warnattr(msg) __attribute__((__warning__ (msg)))
 # define __errordecl(name, msg) \
diff --git a/lib/fpending.c b/lib/fpending.c
index afa840b8512..e57155e586e 100644
--- a/lib/fpending.c
+++ b/lib/fpending.c
@@ -41,7 +41,7 @@ __fpending (FILE *fp)
   return fp->_IO_write_ptr - fp->_IO_write_base;
 #elif defined __sferror || defined __DragonFly__ || defined __ANDROID__
   /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin < 1.7.34, Minix 3, 
Android */
-  return fp->_p - fp->_bf._base;
+  return fp_->_p - fp_->_bf._base;
 #elif defined __EMX__                /* emx+gcc */
   return fp->_ptr - fp->_buffer;
 #elif defined __minix                /* Minix */
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in
index 2097850c812..53a821b141e 100644
--- a/lib/gnulib.mk.in
+++ b/lib/gnulib.mk.in
@@ -68,6 +68,7 @@
 #  --avoid=wchar \
 #  --avoid=wcrtomb \
 #  --avoid=wctype-h \
+#  alignasof \
 #  alloca-opt \
 #  binary-io \
 #  byteswap \
@@ -145,7 +146,6 @@
 #  socklen \
 #  stat-time \
 #  std-gnu11 \
-#  stdalign \
 #  stdbool \
 #  stddef \
 #  stdio \
@@ -325,7 +325,6 @@ GL_GENERATE_GMP_H_CONDITION = @GL_GENERATE_GMP_H_CONDITION@
 GL_GENERATE_IEEE754_H_CONDITION = @GL_GENERATE_IEEE754_H_CONDITION@
 GL_GENERATE_LIMITS_H_CONDITION = @GL_GENERATE_LIMITS_H_CONDITION@
 GL_GENERATE_MINI_GMP_H_CONDITION = @GL_GENERATE_MINI_GMP_H_CONDITION@
-GL_GENERATE_STDALIGN_H_CONDITION = @GL_GENERATE_STDALIGN_H_CONDITION@
 GL_GENERATE_STDCKDINT_H_CONDITION = @GL_GENERATE_STDCKDINT_H_CONDITION@
 GL_GENERATE_STDDEF_H_CONDITION = @GL_GENERATE_STDDEF_H_CONDITION@
 GL_GENERATE_STDINT_H_CONDITION = @GL_GENERATE_STDINT_H_CONDITION@
@@ -411,6 +410,7 @@ GL_GNULIB_GETOPT_POSIX = @GL_GNULIB_GETOPT_POSIX@
 GL_GNULIB_GETPAGESIZE = @GL_GNULIB_GETPAGESIZE@
 GL_GNULIB_GETPASS = @GL_GNULIB_GETPASS@
 GL_GNULIB_GETPASS_GNU = @GL_GNULIB_GETPASS_GNU@
+GL_GNULIB_GETPROGNAME = @GL_GNULIB_GETPROGNAME@
 GL_GNULIB_GETRANDOM = @GL_GNULIB_GETRANDOM@
 GL_GNULIB_GETSUBOPT = @GL_GNULIB_GETSUBOPT@
 GL_GNULIB_GETTIMEOFDAY = @GL_GNULIB_GETTIMEOFDAY@
@@ -734,6 +734,7 @@ HAVE_GETLOGIN = @HAVE_GETLOGIN@
 HAVE_GETOPT_H = @HAVE_GETOPT_H@
 HAVE_GETPAGESIZE = @HAVE_GETPAGESIZE@
 HAVE_GETPASS = @HAVE_GETPASS@
+HAVE_GETPROGNAME = @HAVE_GETPROGNAME@
 HAVE_GETRANDOM = @HAVE_GETRANDOM@
 HAVE_GETSUBOPT = @HAVE_GETSUBOPT@
 HAVE_GETTIMEOFDAY = @HAVE_GETTIMEOFDAY@
@@ -741,6 +742,8 @@ HAVE_GETUMASK = @HAVE_GETUMASK@
 HAVE_GRANTPT = @HAVE_GRANTPT@
 HAVE_GROUP_MEMBER = @HAVE_GROUP_MEMBER@
 HAVE_GSETTINGS = @HAVE_GSETTINGS@
+HAVE_IMAXABS = @HAVE_IMAXABS@
+HAVE_IMAXDIV = @HAVE_IMAXDIV@
 HAVE_IMAXDIV_T = @HAVE_IMAXDIV_T@
 HAVE_INITSTATE = @HAVE_INITSTATE@
 HAVE_INTTYPES_H = @HAVE_INTTYPES_H@
@@ -1061,6 +1064,7 @@ REPLACE_DIRFD = @REPLACE_DIRFD@
 REPLACE_DPRINTF = @REPLACE_DPRINTF@
 REPLACE_DUP = @REPLACE_DUP@
 REPLACE_DUP2 = @REPLACE_DUP2@
+REPLACE_DUP3 = @REPLACE_DUP3@
 REPLACE_EXECL = @REPLACE_EXECL@
 REPLACE_EXECLE = @REPLACE_EXECLE@
 REPLACE_EXECLP = @REPLACE_EXECLP@
@@ -1073,6 +1077,7 @@ REPLACE_FCHMODAT = @REPLACE_FCHMODAT@
 REPLACE_FCHOWNAT = @REPLACE_FCHOWNAT@
 REPLACE_FCLOSE = @REPLACE_FCLOSE@
 REPLACE_FCNTL = @REPLACE_FCNTL@
+REPLACE_FDATASYNC = @REPLACE_FDATASYNC@
 REPLACE_FDOPEN = @REPLACE_FDOPEN@
 REPLACE_FDOPENDIR = @REPLACE_FDOPENDIR@
 REPLACE_FFLUSH = @REPLACE_FFLUSH@
@@ -1095,15 +1100,21 @@ REPLACE_GETCWD = @REPLACE_GETCWD@
 REPLACE_GETDELIM = @REPLACE_GETDELIM@
 REPLACE_GETDOMAINNAME = @REPLACE_GETDOMAINNAME@
 REPLACE_GETDTABLESIZE = @REPLACE_GETDTABLESIZE@
+REPLACE_GETENTROPY = @REPLACE_GETENTROPY@
 REPLACE_GETGROUPS = @REPLACE_GETGROUPS@
 REPLACE_GETLINE = @REPLACE_GETLINE@
+REPLACE_GETLOADAVG = @REPLACE_GETLOADAVG@
 REPLACE_GETLOGIN_R = @REPLACE_GETLOGIN_R@
 REPLACE_GETPAGESIZE = @REPLACE_GETPAGESIZE@
 REPLACE_GETPASS = @REPLACE_GETPASS@
 REPLACE_GETPASS_FOR_GETPASS_GNU = @REPLACE_GETPASS_FOR_GETPASS_GNU@
+REPLACE_GETPROGNAME = @REPLACE_GETPROGNAME@
 REPLACE_GETRANDOM = @REPLACE_GETRANDOM@
+REPLACE_GETSUBOPT = @REPLACE_GETSUBOPT@
 REPLACE_GETTIMEOFDAY = @REPLACE_GETTIMEOFDAY@
 REPLACE_GMTIME = @REPLACE_GMTIME@
+REPLACE_IMAXABS = @REPLACE_IMAXABS@
+REPLACE_IMAXDIV = @REPLACE_IMAXDIV@
 REPLACE_INITSTATE = @REPLACE_INITSTATE@
 REPLACE_ISATTY = @REPLACE_ISATTY@
 REPLACE_LCHOWN = @REPLACE_LCHOWN@
@@ -1118,11 +1129,14 @@ REPLACE_MALLOC_FOR_MALLOC_POSIX = 
@REPLACE_MALLOC_FOR_MALLOC_POSIX@
 REPLACE_MBTOWC = @REPLACE_MBTOWC@
 REPLACE_MEMCHR = @REPLACE_MEMCHR@
 REPLACE_MEMMEM = @REPLACE_MEMMEM@
+REPLACE_MEMPCPY = @REPLACE_MEMPCPY@
 REPLACE_MKDIR = @REPLACE_MKDIR@
 REPLACE_MKFIFO = @REPLACE_MKFIFO@
 REPLACE_MKFIFOAT = @REPLACE_MKFIFOAT@
 REPLACE_MKNOD = @REPLACE_MKNOD@
 REPLACE_MKNODAT = @REPLACE_MKNODAT@
+REPLACE_MKOSTEMP = @REPLACE_MKOSTEMP@
+REPLACE_MKOSTEMPS = @REPLACE_MKOSTEMPS@
 REPLACE_MKSTEMP = @REPLACE_MKSTEMP@
 REPLACE_MKTIME = @REPLACE_MKTIME@
 REPLACE_NANOSLEEP = @REPLACE_NANOSLEEP@
@@ -1132,8 +1146,10 @@ REPLACE_OPEN = @REPLACE_OPEN@
 REPLACE_OPENAT = @REPLACE_OPENAT@
 REPLACE_OPENDIR = @REPLACE_OPENDIR@
 REPLACE_PERROR = @REPLACE_PERROR@
+REPLACE_PIPE2 = @REPLACE_PIPE2@
 REPLACE_POPEN = @REPLACE_POPEN@
 REPLACE_POSIX_MEMALIGN = @REPLACE_POSIX_MEMALIGN@
+REPLACE_POSIX_OPENPT = @REPLACE_POSIX_OPENPT@
 REPLACE_PREAD = @REPLACE_PREAD@
 REPLACE_PRINTF = @REPLACE_PRINTF@
 REPLACE_PSELECT = @REPLACE_PSELECT@
@@ -1159,6 +1175,7 @@ REPLACE_RENAMEAT = @REPLACE_RENAMEAT@
 REPLACE_RMDIR = @REPLACE_RMDIR@
 REPLACE_SELECT = @REPLACE_SELECT@
 REPLACE_SETENV = @REPLACE_SETENV@
+REPLACE_SETHOSTNAME = @REPLACE_SETHOSTNAME@
 REPLACE_SETSTATE = @REPLACE_SETSTATE@
 REPLACE_SLEEP = @REPLACE_SLEEP@
 REPLACE_SNPRINTF = @REPLACE_SNPRINTF@
@@ -1166,6 +1183,7 @@ REPLACE_SPRINTF = @REPLACE_SPRINTF@
 REPLACE_STAT = @REPLACE_STAT@
 REPLACE_STDIO_READ_FUNCS = @REPLACE_STDIO_READ_FUNCS@
 REPLACE_STDIO_WRITE_FUNCS = @REPLACE_STDIO_WRITE_FUNCS@
+REPLACE_STPCPY = @REPLACE_STPCPY@
 REPLACE_STPNCPY = @REPLACE_STPNCPY@
 REPLACE_STRCASESTR = @REPLACE_STRCASESTR@
 REPLACE_STRCHRNUL = @REPLACE_STRCHRNUL@
@@ -1192,6 +1210,7 @@ REPLACE_STRUCT_TIMEVAL = @REPLACE_STRUCT_TIMEVAL@
 REPLACE_SYMLINK = @REPLACE_SYMLINK@
 REPLACE_SYMLINKAT = @REPLACE_SYMLINKAT@
 REPLACE_TIMEGM = @REPLACE_TIMEGM@
+REPLACE_TIMESPEC_GET = @REPLACE_TIMESPEC_GET@
 REPLACE_TMPFILE = @REPLACE_TMPFILE@
 REPLACE_TRUNCATE = @REPLACE_TRUNCATE@
 REPLACE_TTYNAME_R = @REPLACE_TTYNAME_R@
@@ -1209,6 +1228,7 @@ REPLACE_VSNPRINTF = @REPLACE_VSNPRINTF@
 REPLACE_VSPRINTF = @REPLACE_VSPRINTF@
 REPLACE_WCTOMB = @REPLACE_WCTOMB@
 REPLACE_WRITE = @REPLACE_WRITE@
+REPLACE__EXIT = @REPLACE__EXIT@
 RSVG_CFLAGS = @RSVG_CFLAGS@
 RSVG_LIBS = @RSVG_LIBS@
 SEPCHAR = @SEPCHAR@
@@ -1221,7 +1241,6 @@ SIZEOF_LONG = @SIZEOF_LONG@
 SIZE_T_SUFFIX = @SIZE_T_SUFFIX@
 SMALL_JA_DIC = @SMALL_JA_DIC@
 SQLITE3_LIBS = @SQLITE3_LIBS@
-STDALIGN_H = @STDALIGN_H@
 STDCKDINT_H = @STDCKDINT_H@
 STDDEF_H = @STDDEF_H@
 STDINT_H = @STDINT_H@
@@ -2369,6 +2388,8 @@ inttypes.h: inttypes.in.h $(top_builddir)/config.status 
$(CXXDEFS_H) $(WARN_ON_U
              -e 's/@''HAVE_DECL_STRTOIMAX''@/$(HAVE_DECL_STRTOIMAX)/g' \
              -e 's/@''HAVE_DECL_STRTOUMAX''@/$(HAVE_DECL_STRTOUMAX)/g' \
              -e 's/@''HAVE_IMAXDIV_T''@/$(HAVE_IMAXDIV_T)/g' \
+             -e 's/@''REPLACE_IMAXABS''@/$(REPLACE_IMAXABS)/g' \
+             -e 's/@''REPLACE_IMAXDIV''@/$(REPLACE_IMAXDIV)/g' \
              -e 's/@''REPLACE_STRTOIMAX''@/$(REPLACE_STRTOIMAX)/g' \
              -e 's/@''REPLACE_STRTOUMAX''@/$(REPLACE_STRTOUMAX)/g' \
              -e 's/@''INT32_MAX_LT_INTMAX_MAX''@/$(INT32_MAX_LT_INTMAX_MAX)/g' 
\
@@ -2907,28 +2928,6 @@ EXTRA_DIST += stat-time.h
 endif
 ## end   gnulib module stat-time
 
-## begin gnulib module stdalign
-ifeq (,$(OMIT_GNULIB_MODULE_stdalign))
-
-BUILT_SOURCES += $(STDALIGN_H)
-
-# We need the following in order to create <stdalign.h> when the system
-# doesn't have one that works.
-ifneq (,$(GL_GENERATE_STDALIGN_H_CONDITION))
-stdalign.h: stdalign.in.h $(top_builddir)/config.status
-       $(gl_V_at)$(SED_HEADER_TO_AT_t) $(srcdir)/stdalign.in.h
-       $(AM_V_at)mv $@-t $@
-else
-stdalign.h: $(top_builddir)/config.status
-       rm -f $@
-endif
-MOSTLYCLEANFILES += stdalign.h stdalign.h-t
-
-EXTRA_DIST += stdalign.in.h
-
-endif
-## end   gnulib module stdalign
-
 ## begin gnulib module stdckdint
 ifeq (,$(OMIT_GNULIB_MODULE_stdckdint))
 
@@ -3203,6 +3202,7 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status 
$(CXXDEFS_H) \
              -e 
's/@''GNULIB_CANONICALIZE_FILE_NAME''@/$(GL_GNULIB_CANONICALIZE_FILE_NAME)/g' \
              -e 's/@''GNULIB_FREE_POSIX''@/$(GL_GNULIB_FREE_POSIX)/g' \
              -e 's/@''GNULIB_GETLOADAVG''@/$(GL_GNULIB_GETLOADAVG)/g' \
+             -e 's/@''GNULIB_GETPROGNAME''@/$(GL_GNULIB_GETPROGNAME)/g' \
              -e 's/@''GNULIB_GETSUBOPT''@/$(GL_GNULIB_GETSUBOPT)/g' \
              -e 's/@''GNULIB_GRANTPT''@/$(GL_GNULIB_GRANTPT)/g' \
              -e 's/@''GNULIB_MALLOC_GNU''@/$(GL_GNULIB_MALLOC_GNU)/g' \
@@ -3252,6 +3252,7 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status 
$(CXXDEFS_H) \
              -e 's|@''HAVE_DECL_FCVT''@|$(HAVE_DECL_FCVT)|g' \
              -e 's|@''HAVE_DECL_GCVT''@|$(HAVE_DECL_GCVT)|g' \
              -e 's|@''HAVE_DECL_GETLOADAVG''@|$(HAVE_DECL_GETLOADAVG)|g' \
+             -e 's|@''HAVE_GETPROGNAME''@|$(HAVE_GETPROGNAME)|g' \
              -e 's|@''HAVE_GETSUBOPT''@|$(HAVE_GETSUBOPT)|g' \
              -e 's|@''HAVE_GRANTPT''@|$(HAVE_GRANTPT)|g' \
              -e 's|@''HAVE_INITSTATE''@|$(HAVE_INITSTATE)|g' \
@@ -3287,17 +3288,24 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status 
$(CXXDEFS_H) \
              -e 's|@''HAVE_SYS_LOADAVG_H''@|$(HAVE_SYS_LOADAVG_H)|g' \
              -e 's|@''HAVE_UNLOCKPT''@|$(HAVE_UNLOCKPT)|g' \
              -e 's|@''HAVE_DECL_UNSETENV''@|$(HAVE_DECL_UNSETENV)|g' \
+             -e 's|@''REPLACE__EXIT''@|$(REPLACE__EXIT)|g' \
              -e 's|@''REPLACE_ALIGNED_ALLOC''@|$(REPLACE_ALIGNED_ALLOC)|g' \
              -e 
's|@''REPLACE_CALLOC_FOR_CALLOC_GNU''@|$(REPLACE_CALLOC_FOR_CALLOC_GNU)|g' \
              -e 
's|@''REPLACE_CALLOC_FOR_CALLOC_POSIX''@|$(REPLACE_CALLOC_FOR_CALLOC_POSIX)|g' \
              -e 
's|@''REPLACE_CANONICALIZE_FILE_NAME''@|$(REPLACE_CANONICALIZE_FILE_NAME)|g' \
              -e 's|@''REPLACE_FREE''@|$(REPLACE_FREE)|g' \
+             -e 's|@''REPLACE_GETLOADAVG''@|$(REPLACE_GETLOADAVG)|g' \
+             -e 's|@''REPLACE_GETPROGNAME''@|$(REPLACE_GETPROGNAME)|g' \
+             -e 's|@''REPLACE_GETSUBOPT''@|$(REPLACE_GETSUBOPT)|g' \
              -e 's|@''REPLACE_INITSTATE''@|$(REPLACE_INITSTATE)|g' \
              -e 
's|@''REPLACE_MALLOC_FOR_MALLOC_GNU''@|$(REPLACE_MALLOC_FOR_MALLOC_GNU)|g' \
              -e 
's|@''REPLACE_MALLOC_FOR_MALLOC_POSIX''@|$(REPLACE_MALLOC_FOR_MALLOC_POSIX)|g' \
              -e 's|@''REPLACE_MBTOWC''@|$(REPLACE_MBTOWC)|g' \
+             -e 's|@''REPLACE_MKOSTEMP''@|$(REPLACE_MKOSTEMP)|g' \
+             -e 's|@''REPLACE_MKOSTEMPS''@|$(REPLACE_MKOSTEMPS)|g' \
              -e 's|@''REPLACE_MKSTEMP''@|$(REPLACE_MKSTEMP)|g' \
              -e 's|@''REPLACE_POSIX_MEMALIGN''@|$(REPLACE_POSIX_MEMALIGN)|g' \
+             -e 's|@''REPLACE_POSIX_OPENPT''@|$(REPLACE_POSIX_OPENPT)|g' \
              -e 's|@''REPLACE_PTSNAME''@|$(REPLACE_PTSNAME)|g' \
              -e 's|@''REPLACE_PTSNAME_R''@|$(REPLACE_PTSNAME_R)|g' \
              -e 's|@''REPLACE_PUTENV''@|$(REPLACE_PUTENV)|g' \
@@ -3429,7 +3437,9 @@ string.h: string.in.h $(top_builddir)/config.status 
$(CXXDEFS_H) $(ARG_NONNULL_H
              -e 's|@''REPLACE_FFSLL''@|$(REPLACE_FFSLL)|g' \
              -e 's|@''REPLACE_MEMCHR''@|$(REPLACE_MEMCHR)|g' \
              -e 's|@''REPLACE_MEMMEM''@|$(REPLACE_MEMMEM)|g' \
+             -e 's|@''REPLACE_MEMPCPY''@|$(REPLACE_MEMPCPY)|g' \
              -e 's|@''REPLACE_FREE''@|$(REPLACE_FREE)|g' \
+             -e 's|@''REPLACE_STPCPY''@|$(REPLACE_STPCPY)|g' \
              -e 's|@''REPLACE_STPNCPY''@|$(REPLACE_STPNCPY)|g' \
              -e 's|@''REPLACE_STRCHRNUL''@|$(REPLACE_STRCHRNUL)|g' \
              -e 's|@''REPLACE_STRDUP''@|$(REPLACE_STRDUP)|g' \
@@ -3755,6 +3765,7 @@ time.h: time.in.h $(top_builddir)/config.status 
$(CXXDEFS_H) $(ARG_NONNULL_H) $(
              -e 's|@''REPLACE_NANOSLEEP''@|$(REPLACE_NANOSLEEP)|g' \
              -e 's|@''REPLACE_STRFTIME''@|$(REPLACE_STRFTIME)|g' \
              -e 's|@''REPLACE_TIMEGM''@|$(REPLACE_TIMEGM)|g' \
+             -e 's|@''REPLACE_TIMESPEC_GET''@|$(REPLACE_TIMESPEC_GET)|g' \
              -e 's|@''REPLACE_TZSET''@|$(REPLACE_TZSET)|g' \
              -e 
's|@''PTHREAD_H_DEFINES_STRUCT_TIMESPEC''@|$(PTHREAD_H_DEFINES_STRUCT_TIMESPEC)|g'
 \
              -e 
's|@''SYS_TIME_H_DEFINES_STRUCT_TIMESPEC''@|$(SYS_TIME_H_DEFINES_STRUCT_TIMESPEC)|g'
 \
@@ -3999,6 +4010,7 @@ unistd.h: unistd.in.h $(top_builddir)/config.status 
$(CXXDEFS_H) $(ARG_NONNULL_H
              -e 's|@''REPLACE_COPY_FILE_RANGE''@|$(REPLACE_COPY_FILE_RANGE)|g' 
\
              -e 's|@''REPLACE_DUP''@|$(REPLACE_DUP)|g' \
              -e 's|@''REPLACE_DUP2''@|$(REPLACE_DUP2)|g' \
+             -e 's|@''REPLACE_DUP3''@|$(REPLACE_DUP3)|g' \
              -e 's|@''REPLACE_EXECL''@|$(REPLACE_EXECL)|g' \
              -e 's|@''REPLACE_EXECLE''@|$(REPLACE_EXECLE)|g' \
              -e 's|@''REPLACE_EXECLP''@|$(REPLACE_EXECLP)|g' \
@@ -4008,10 +4020,12 @@ unistd.h: unistd.in.h $(top_builddir)/config.status 
$(CXXDEFS_H) $(ARG_NONNULL_H
              -e 's|@''REPLACE_EXECVPE''@|$(REPLACE_EXECVPE)|g' \
              -e 's|@''REPLACE_FACCESSAT''@|$(REPLACE_FACCESSAT)|g' \
              -e 's|@''REPLACE_FCHOWNAT''@|$(REPLACE_FCHOWNAT)|g' \
+             -e 's|@''REPLACE_FDATASYNC''@|$(REPLACE_FDATASYNC)|g' \
              -e 's|@''REPLACE_FTRUNCATE''@|$(REPLACE_FTRUNCATE)|g' \
              -e 's|@''REPLACE_GETCWD''@|$(REPLACE_GETCWD)|g' \
              -e 's|@''REPLACE_GETDOMAINNAME''@|$(REPLACE_GETDOMAINNAME)|g' \
              -e 's|@''REPLACE_GETDTABLESIZE''@|$(REPLACE_GETDTABLESIZE)|g' \
+             -e 's|@''REPLACE_GETENTROPY''@|$(REPLACE_GETENTROPY)|g' \
              -e 's|@''REPLACE_GETLOGIN_R''@|$(REPLACE_GETLOGIN_R)|g' \
              -e 's|@''REPLACE_GETGROUPS''@|$(REPLACE_GETGROUPS)|g' \
              -e 's|@''REPLACE_GETPAGESIZE''@|$(REPLACE_GETPAGESIZE)|g' \
@@ -4022,12 +4036,14 @@ unistd.h: unistd.in.h $(top_builddir)/config.status 
$(CXXDEFS_H) $(ARG_NONNULL_H
              -e 's|@''REPLACE_LINK''@|$(REPLACE_LINK)|g' \
              -e 's|@''REPLACE_LINKAT''@|$(REPLACE_LINKAT)|g' \
              -e 's|@''REPLACE_LSEEK''@|$(REPLACE_LSEEK)|g' \
+             -e 's|@''REPLACE_PIPE2''@|$(REPLACE_PIPE2)|g' \
              -e 's|@''REPLACE_PREAD''@|$(REPLACE_PREAD)|g' \
              -e 's|@''REPLACE_PWRITE''@|$(REPLACE_PWRITE)|g' \
              -e 's|@''REPLACE_READ''@|$(REPLACE_READ)|g' \
              -e 's|@''REPLACE_READLINK''@|$(REPLACE_READLINK)|g' \
              -e 's|@''REPLACE_READLINKAT''@|$(REPLACE_READLINKAT)|g' \
              -e 's|@''REPLACE_RMDIR''@|$(REPLACE_RMDIR)|g' \
+             -e 's|@''REPLACE_SETHOSTNAME''@|$(REPLACE_SETHOSTNAME)|g' \
              -e 's|@''REPLACE_SLEEP''@|$(REPLACE_SLEEP)|g' \
              -e 's|@''REPLACE_SYMLINK''@|$(REPLACE_SYMLINK)|g' \
              -e 's|@''REPLACE_SYMLINKAT''@|$(REPLACE_SYMLINKAT)|g' \
diff --git a/lib/inttypes.in.h b/lib/inttypes.in.h
index 50a2bbfcda2..5b7ef12dc7e 100644
--- a/lib/inttypes.in.h
+++ b/lib/inttypes.in.h
@@ -903,8 +903,21 @@ extern "C" {
 #endif
 
 #if @GNULIB_IMAXABS@
-# if !@HAVE_DECL_IMAXABS@
-extern intmax_t imaxabs (intmax_t);
+# if @REPLACE_IMAXABS@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef imaxabs
+#   define imaxabs rpl_imaxabs
+#  endif
+_GL_FUNCDECL_RPL (imaxabs, intmax_t, (intmax_t x));
+_GL_CXXALIAS_RPL (imaxabs, intmax_t, (intmax_t x));
+# else
+#  if !@HAVE_DECL_IMAXABS@
+_GL_FUNCDECL_SYS (imaxabs, intmax_t, (intmax_t x));
+#  endif
+_GL_CXXALIAS_SYS (imaxabs, intmax_t, (intmax_t x));
+# endif
+# if __GLIBC__ >= 2
+_GL_CXXALIASWARN (imaxabs);
 # endif
 #elif defined GNULIB_POSIXCHECK
 # undef imaxabs
@@ -921,8 +934,21 @@ typedef struct { intmax_t quot; intmax_t rem; } imaxdiv_t;
 #   define GNULIB_defined_imaxdiv_t 1
 #  endif
 # endif
-# if !@HAVE_DECL_IMAXDIV@
-extern imaxdiv_t imaxdiv (intmax_t, intmax_t);
+# if @REPLACE_IMAXDIV@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef imaxdiv
+#   define imaxdiv rpl_imaxdiv
+#  endif
+_GL_FUNCDECL_RPL (imaxdiv, imaxdiv_t, (intmax_t numer, intmax_t denom));
+_GL_CXXALIAS_RPL (imaxdiv, imaxdiv_t, (intmax_t numer, intmax_t denom));
+# else
+#  if !@HAVE_DECL_IMAXDIV@
+_GL_FUNCDECL_SYS (imaxdiv, imaxdiv_t, (intmax_t numer, intmax_t denom));
+#  endif
+_GL_CXXALIAS_SYS (imaxdiv, imaxdiv_t, (intmax_t numer, intmax_t denom));
+# endif
+# if __GLIBC__ >= 2
+_GL_CXXALIASWARN (imaxdiv);
 # endif
 #elif defined GNULIB_POSIXCHECK
 # undef imaxdiv
diff --git a/lib/libc-config.h b/lib/libc-config.h
index 1d28e58c971..5f5ad010377 100644
--- a/lib/libc-config.h
+++ b/lib/libc-config.h
@@ -137,8 +137,6 @@
 # undef __attribute_returns_twice__
 # undef __attribute_used__
 # undef __attribute_warn_unused_result__
-# undef __bos
-# undef __bos0
 # undef __errordecl
 # undef __extension__
 # undef __extern_always_inline
@@ -147,21 +145,13 @@
 # undef __fortified_attr_access
 # undef __fortify_function
 # undef __glibc_c99_flexarr_available
-# undef __glibc_fortify
-# undef __glibc_fortify_n
 # undef __glibc_has_attribute
 # undef __glibc_has_builtin
 # undef __glibc_has_extension
 # undef __glibc_likely
 # undef __glibc_macro_warning
 # undef __glibc_macro_warning1
-# undef __glibc_objsize
-# undef __glibc_objsize0
-# undef __glibc_safe_len_cond
-# undef __glibc_safe_or_unknown_len
 # undef __glibc_unlikely
-# undef __glibc_unsafe_len
-# undef __glibc_unsigned_or_positive
 # undef __inline
 # undef __ptr_t
 # undef __restrict
@@ -170,6 +160,18 @@
 # undef __va_arg_pack_len
 # undef __warnattr
 # undef __wur
+# ifndef __GNULIB_CDEFS
+#  undef __bos
+#  undef __bos0
+#  undef __glibc_fortify
+#  undef __glibc_fortify_n
+#  undef __glibc_objsize
+#  undef __glibc_objsize0
+#  undef __glibc_safe_len_cond
+#  undef __glibc_safe_or_unknown_len
+#  undef __glibc_unsafe_len
+#  undef __glibc_unsigned_or_positive
+# endif
 
 /* Include our copy of glibc <sys/cdefs.h>.  */
 # include <cdefs.h>
diff --git a/lib/openat-proc.c b/lib/openat-proc.c
index 2a6a85f0696..88f70be4f59 100644
--- a/lib/openat-proc.c
+++ b/lib/openat-proc.c
@@ -30,9 +30,12 @@
 #include <string.h>
 #include <unistd.h>
 
-#ifdef __KLIBC__
+#ifdef __KLIBC__ /* OS/2 */
 # include <InnoTekLIBC/backend.h>
 #endif
+#ifdef __MVS__ /* z/OS */
+# include <termios.h>
+#endif
 
 #include "intprops.h"
 
@@ -53,7 +56,8 @@ openat_proc_name (char buf[OPENAT_BUFFER_SIZE], int fd, char 
const *file)
       return buf;
     }
 
-#ifndef __KLIBC__
+#if !(defined __KLIBC__ || defined __MVS__)
+  /* Generic code for Linux, Solaris, and similar platforms.  */
 # define PROC_SELF_FD_FORMAT "/proc/self/fd/%d/"
   {
     enum {
@@ -107,14 +111,29 @@ openat_proc_name (char buf[OPENAT_BUFFER_SIZE], int fd, 
char const *file)
         dirlen = sprintf (result, PROC_SELF_FD_FORMAT, fd);
       }
   }
-#else
+#else /* (defined __KLIBC__ || defined __MVS__), i.e. OS/2 or z/OS */
   /* OS/2 kLIBC provides a function to retrieve a path from a fd.  */
   {
-    char dir[_MAX_PATH];
     size_t bufsize;
 
+# ifdef __KLIBC__
+    char dir[_MAX_PATH];
     if (__libc_Back_ioFHToPath (fd, dir, sizeof dir))
       return NULL;
+# endif
+# ifdef __MVS__
+    char dir[_XOPEN_PATH_MAX];
+    /* Documentation:
+       
https://www.ibm.com/docs/en/zos/2.2.0?topic=functions-w-ioctl-w-pioctl-control-devices
 */
+    if (w_ioctl (fd, _IOCC_GPN, sizeof dir, dir) < 0)
+      return NULL;
+    /* Documentation:
+       
https://www.ibm.com/docs/en/zos/2.2.0?topic=functions-e2a-l-convert-characters-from-ebcdic-ascii
 */
+    dirlen = __e2a_l (dir, strlen (dir));
+    if (dirlen < 0 || dirlen >= sizeof dir)
+      return NULL;
+    dir[dirlen] = '\0';
+# endif
 
     dirlen = strlen (dir);
     bufsize = dirlen + 1 + strlen (file) + 1; /* 1 for '/', 1 for null */
diff --git a/lib/stdalign.in.h b/lib/stdalign.in.h
deleted file mode 100644
index 17357810c7c..00000000000
--- a/lib/stdalign.in.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/* A substitute for ISO C11 <stdalign.h>.
-
-   Copyright 2011-2023 Free Software Foundation, Inc.
-
-   This file is free software: you can redistribute it and/or modify
-   it under the terms of the GNU Lesser General Public License as
-   published by the Free Software Foundation; either version 2.1 of the
-   License, or (at your option) any later version.
-
-   This file is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public License
-   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
-
-/* Written by Paul Eggert and Bruno Haible.  */
-
-#ifndef _GL_STDALIGN_H
-#define _GL_STDALIGN_H
-
-/* ISO C11 <stdalign.h> for platforms that lack it.
-
-   References:
-   ISO C11 (latest free draft
-   <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf>)
-   sections 6.5.3.4, 6.7.5, 7.15.
-   C++11 (latest free draft
-   <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf>)
-   section 18.10. */
-
-/* alignof (TYPE), also known as _Alignof (TYPE), yields the alignment
-   requirement of a structure member (i.e., slot or field) that is of
-   type TYPE, as an integer constant expression.
-
-   This differs from GCC's and clang's __alignof__ operator, which can
-   yield a better-performing alignment for an object of that type.  For
-   example, on x86 with GCC and on Linux/x86 with clang,
-   __alignof__ (double) and __alignof__ (long long) are 8, whereas
-   alignof (double) and alignof (long long) are 4 unless the option
-   '-malign-double' is used.
-
-   The result cannot be used as a value for an 'enum' constant, if you
-   want to be portable to HP-UX 10.20 cc and AIX 3.2.5 xlc.  */
-
-/* FreeBSD 9.1 <sys/cdefs.h>, included by <stddef.h> and lots of other
-   standard headers, defines conflicting implementations of _Alignas
-   and _Alignof that are no better than ours; override them.  */
-#undef _Alignas
-#undef _Alignof
-
-/* GCC releases before GCC 4.9 had a bug in _Alignof.  See GCC bug 52023
-   <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52023>.
-   clang versions < 8.0.0 have the same bug.  */
-#if (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112 \
-     || (defined __GNUC__ && __GNUC__ < 4 + (__GNUC_MINOR__ < 9) \
-         && !defined __clang__) \
-     || (defined __clang__ && __clang_major__ < 8))
-# ifdef __cplusplus
-#  if (201103 <= __cplusplus || defined _MSC_VER)
-#   define _Alignof(type) alignof (type)
-#  else
-   template <class __t> struct __alignof_helper { char __a; __t __b; };
-#   define _Alignof(type) offsetof (__alignof_helper<type>, __b)
-#   define _GL_STDALIGN_NEEDS_STDDEF 1
-#  endif
-# else
-#  define _Alignof(type) offsetof (struct { char __a; type __b; }, __b)
-#  define _GL_STDALIGN_NEEDS_STDDEF 1
-# endif
-#endif
-#if ! (defined __cplusplus && (201103 <= __cplusplus || defined _MSC_VER))
-# define alignof _Alignof
-#endif
-#define __alignof_is_defined 1
-
-/* alignas (A), also known as _Alignas (A), aligns a variable or type
-   to the alignment A, where A is an integer constant expression.  For
-   example:
-
-      int alignas (8) foo;
-      struct s { int a; int alignas (8) bar; };
-
-   aligns the address of FOO and the offset of BAR to be multiples of 8.
-
-   A should be a power of two that is at least the type's alignment
-   and at most the implementation's alignment limit.  This limit is
-   2**28 on typical GNUish hosts, and 2**13 on MSVC.  To be portable
-   to MSVC through at least version 10.0, A should be an integer
-   constant, as MSVC does not support expressions such as 1 << 3.
-   To be portable to Sun C 5.11, do not align auto variables to
-   anything stricter than their default alignment.
-
-   The following C11 requirements are not supported here:
-
-     - If A is zero, alignas has no effect.
-     - alignas can be used multiple times; the strictest one wins.
-     - alignas (TYPE) is equivalent to alignas (alignof (TYPE)).
-
-   */
-
-#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112
-# if defined __cplusplus && (201103 <= __cplusplus || defined _MSC_VER)
-#  define _Alignas(a) alignas (a)
-# elif (!defined __attribute__ \
-        && ((defined __APPLE__ && defined __MACH__ \
-             ? 4 < __GNUC__ + (1 <= __GNUC_MINOR__) \
-             : __GNUC__ && !defined __ibmxl__) \
-            || (4 <= __clang_major__) \
-            || (__ia64 && (61200 <= __HP_cc || 61200 <= __HP_aCC)) \
-            || __ICC || 0x590 <= __SUNPRO_C || 0x0600 <= __xlC__))
-#  define _Alignas(a) __attribute__ ((__aligned__ (a)))
-# elif 1300 <= _MSC_VER
-#  define _Alignas(a) __declspec (align (a))
-# endif
-#endif
-#if ((defined _Alignas \
-      && !(defined __cplusplus && (201103 <= __cplusplus || defined 
_MSC_VER))) \
-     || (defined __STDC_VERSION__ && 201112 <= __STDC_VERSION__))
-# define alignas _Alignas
-#endif
-#if (defined alignas \
-     || (defined __cplusplus && (201103 <= __cplusplus || defined _MSC_VER)))
-# define __alignas_is_defined 1
-#endif
-
-/* Include <stddef.h> if needed for offsetof.  */
-#if _GL_STDALIGN_NEEDS_STDDEF
-# include <stddef.h>
-#endif
-
-#endif /* _GL_STDALIGN_H */
diff --git a/lib/stdio-impl.h b/lib/stdio-impl.h
index 81e7f838372..46608bed198 100644
--- a/lib/stdio-impl.h
+++ b/lib/stdio-impl.h
@@ -70,6 +70,12 @@
 #   define _gl_flags_file_t int
 #  else
 #   define _gl_flags_file_t short
+#  endif
+#  ifdef __LP64__
+#   define _gl_file_offset_t int64_t
+#  else
+    /* see 
https://android.googlesource.com/platform/bionic/+/master/docs/32-bit-abi.md */
+#   define _gl_file_offset_t __kernel_off_t
 #  endif
   /* Up to this commit from 2015-10-12
      
<https://android.googlesource.com/platform/bionic.git/+/f0141dfab10a4b332769d52fa76631a64741297a>
@@ -96,7 +102,7 @@
                          unsigned char _nbuf[1]; \
                          struct { unsigned char *_base; size_t _size; } _lb; \
                          int _blksize; \
-                         fpos_t _offset; \
+                         _gl_file_offset_t _offset; \
                          /* More fields, not relevant here.  */ \
                        } *) fp)
 # else
diff --git a/lib/stdio.in.h b/lib/stdio.in.h
index 8b5ef4bd2dd..3f8ea985335 100644
--- a/lib/stdio.in.h
+++ b/lib/stdio.in.h
@@ -210,7 +210,9 @@ _GL_FUNCDECL_SYS (dprintf, int, (int fd, const char 
*restrict format, ...)
 #  endif
 _GL_CXXALIAS_SYS (dprintf, int, (int fd, const char *restrict format, ...));
 # endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (dprintf);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef dprintf
 # if HAVE_RAW_DECL_DPRINTF
@@ -882,7 +884,9 @@ _GL_CXXALIAS_SYS (getdelim, ssize_t,
                    int delimiter,
                    FILE *restrict stream));
 # endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (getdelim);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef getdelim
 # if HAVE_RAW_DECL_GETDELIM
@@ -921,7 +925,7 @@ _GL_CXXALIAS_SYS (getline, ssize_t,
                   (char **restrict lineptr, size_t *restrict linesize,
                    FILE *restrict stream));
 # endif
-# if @HAVE_DECL_GETLINE@
+# if __GLIBC__ >= 2 && @HAVE_DECL_GETLINE@
 _GL_CXXALIASWARN (getline);
 # endif
 #elif defined GNULIB_POSIXCHECK
diff --git a/lib/stdlib.in.h b/lib/stdlib.in.h
index b79e5f70965..a91f4e23d67 100644
--- a/lib/stdlib.in.h
+++ b/lib/stdlib.in.h
@@ -164,11 +164,22 @@ struct random_data
 #if @GNULIB__EXIT@
 /* Terminate the current process with the given return code, without running
    the 'atexit' handlers.  */
-# if !@HAVE__EXIT@
+# if @REPLACE__EXIT@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef _Exit
+#   define _Exit rpl__Exit
+#  endif
+_GL_FUNCDECL_RPL (_Exit, _Noreturn void, (int status));
+_GL_CXXALIAS_RPL (_Exit, void, (int status));
+# else
+#  if !@HAVE__EXIT@
 _GL_FUNCDECL_SYS (_Exit, _Noreturn void, (int status));
-# endif
+#  endif
 _GL_CXXALIAS_SYS (_Exit, void, (int status));
+# endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (_Exit);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef _Exit
 # if HAVE_RAW_DECL__EXIT
@@ -416,12 +427,24 @@ _GL_CXXALIASWARN (gcvt);
    The three numbers are the load average of the last 1 minute, the last 5
    minutes, and the last 15 minutes, respectively.
    LOADAVG is an array of NELEM numbers.  */
-# if !@HAVE_DECL_GETLOADAVG@
+# if @REPLACE_GETLOADAVG@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef getloadavg
+#   define getloadavg rpl_getloadavg
+#  endif
+_GL_FUNCDECL_RPL (getloadavg, int, (double loadavg[], int nelem)
+                                   _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (getloadavg, int, (double loadavg[], int nelem));
+# else
+#  if !@HAVE_DECL_GETLOADAVG@
 _GL_FUNCDECL_SYS (getloadavg, int, (double loadavg[], int nelem)
                                    _GL_ARG_NONNULL ((1)));
-# endif
+#  endif
 _GL_CXXALIAS_SYS (getloadavg, int, (double loadavg[], int nelem));
+# endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (getloadavg);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef getloadavg
 # if HAVE_RAW_DECL_GETLOADAVG
@@ -430,6 +453,41 @@ _GL_WARN_ON_USE (getloadavg, "getloadavg is not portable - 
"
 # endif
 #endif
 
+#if @GNULIB_GETPROGNAME@
+/* Return the base name of the executing program.
+   On native Windows this will usually end in ".exe" or ".EXE". */
+# if @REPLACE_GETPROGNAME@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef getprogname
+#   define getprogname rpl_getprogname
+#  endif
+#  ifdef HAVE_DECL_PROGRAM_INVOCATION_NAME
+_GL_FUNCDECL_RPL (getprogname, const char *, (void) _GL_ATTRIBUTE_PURE);
+#  else
+_GL_FUNCDECL_RPL (getprogname, const char *, (void));
+#  endif
+_GL_CXXALIAS_RPL (getprogname, const char *, (void));
+# else
+#  if !@HAVE_GETPROGNAME@
+#   ifdef HAVE_DECL_PROGRAM_INVOCATION_NAME
+_GL_FUNCDECL_SYS (getprogname, const char *, (void) _GL_ATTRIBUTE_PURE);
+#   else
+_GL_FUNCDECL_SYS (getprogname, const char *, (void));
+#   endif
+#  endif
+_GL_CXXALIAS_SYS (getprogname, const char *, (void));
+# endif
+# if __GLIBC__ >= 2
+_GL_CXXALIASWARN (getprogname);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef getprogname
+# if HAVE_RAW_DECL_GETPROGNAME
+_GL_WARN_ON_USE (getprogname, "getprogname is unportable - "
+                 "use gnulib module getprogname for portability");
+# endif
+#endif
+
 #if @GNULIB_GETSUBOPT@
 /* Assuming *OPTIONP is a comma separated list of elements of the form
    "token" or "token=value", getsubopt parses the first of these elements.
@@ -442,14 +500,28 @@ _GL_WARN_ON_USE (getloadavg, "getloadavg is not portable 
- "
    Otherwise it returns -1, and *OPTIONP and *VALUEP are undefined.
    For more details see the POSIX specification.
    https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsubopt.html */
-# if !@HAVE_GETSUBOPT@
+# if @REPLACE_GETSUBOPT@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef getsubopt
+#   define getsubopt rpl_getsubopt
+#  endif
+_GL_FUNCDECL_RPL (getsubopt, int,
+                  (char **optionp, char *const *tokens, char **valuep)
+                  _GL_ARG_NONNULL ((1, 2, 3)));
+_GL_CXXALIAS_RPL (getsubopt, int,
+                  (char **optionp, char *const *tokens, char **valuep));
+# else
+#  if !@HAVE_GETSUBOPT@
 _GL_FUNCDECL_SYS (getsubopt, int,
                   (char **optionp, char *const *tokens, char **valuep)
                   _GL_ARG_NONNULL ((1, 2, 3)));
-# endif
+#  endif
 _GL_CXXALIAS_SYS (getsubopt, int,
                   (char **optionp, char *const *tokens, char **valuep));
+# endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (getsubopt);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef getsubopt
 # if HAVE_RAW_DECL_GETSUBOPT
@@ -579,12 +651,24 @@ _GL_WARN_ON_USE (mkdtemp, "mkdtemp is unportable - "
    implementation.
    Returns the open file descriptor if successful, otherwise -1 and errno
    set.  */
-# if !@HAVE_MKOSTEMP@
+# if @REPLACE_MKOSTEMP@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef mkostemp
+#   define mkostemp rpl_mkostemp
+#  endif
+_GL_FUNCDECL_RPL (mkostemp, int, (char * /*template*/, int /*flags*/)
+                                 _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (mkostemp, int, (char * /*template*/, int /*flags*/));
+# else
+#  if !@HAVE_MKOSTEMP@
 _GL_FUNCDECL_SYS (mkostemp, int, (char * /*template*/, int /*flags*/)
                                  _GL_ARG_NONNULL ((1)));
-# endif
+#  endif
 _GL_CXXALIAS_SYS (mkostemp, int, (char * /*template*/, int /*flags*/));
+# endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (mkostemp);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef mkostemp
 # if HAVE_RAW_DECL_MKOSTEMP
@@ -607,14 +691,28 @@ _GL_WARN_ON_USE (mkostemp, "mkostemp is unportable - "
    implementation.
    Returns the open file descriptor if successful, otherwise -1 and errno
    set.  */
-# if !@HAVE_MKOSTEMPS@
+# if @REPLACE_MKOSTEMPS@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef mkostemps
+#   define mkostemps rpl_mkostemps
+#  endif
+_GL_FUNCDECL_RPL (mkostemps, int,
+                  (char * /*template*/, int /*suffixlen*/, int /*flags*/)
+                  _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (mkostemps, int,
+                  (char * /*template*/, int /*suffixlen*/, int /*flags*/));
+# else
+#  if !@HAVE_MKOSTEMPS@
 _GL_FUNCDECL_SYS (mkostemps, int,
                   (char * /*template*/, int /*suffixlen*/, int /*flags*/)
                   _GL_ARG_NONNULL ((1)));
-# endif
+#  endif
 _GL_CXXALIAS_SYS (mkostemps, int,
                   (char * /*template*/, int /*suffixlen*/, int /*flags*/));
+# endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (mkostemps);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef mkostemps
 # if HAVE_RAW_DECL_MKOSTEMPS
@@ -713,7 +811,7 @@ _GL_CXXALIAS_SYS (posix_memalign, int,
                   (void **memptr, size_t alignment, size_t size));
 #  endif
 # endif
-# if @HAVE_POSIX_MEMALIGN@
+# if __GLIBC__ >= 2 && @HAVE_POSIX_MEMALIGN@
 _GL_CXXALIASWARN (posix_memalign);
 # endif
 #elif defined GNULIB_POSIXCHECK
@@ -727,11 +825,22 @@ _GL_WARN_ON_USE (posix_memalign, "posix_memalign is not 
portable - "
 #if @GNULIB_POSIX_OPENPT@
 /* Return an FD open to the master side of a pseudo-terminal.  Flags should
    include O_RDWR, and may also include O_NOCTTY.  */
-# if !@HAVE_POSIX_OPENPT@
+# if @REPLACE_POSIX_OPENPT@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef posix_openpt
+#   define posix_openpt rpl_posix_openpt
+#  endif
+_GL_FUNCDECL_RPL (posix_openpt, int, (int flags));
+_GL_CXXALIAS_RPL (posix_openpt, int, (int flags));
+# else
+#  if !@HAVE_POSIX_OPENPT@
 _GL_FUNCDECL_SYS (posix_openpt, int, (int flags));
-# endif
+#  endif
 _GL_CXXALIAS_SYS (posix_openpt, int, (int flags));
+# endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (posix_openpt);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef posix_openpt
 # if HAVE_RAW_DECL_POSIX_OPENPT
@@ -956,7 +1065,9 @@ _GL_FUNCDECL_SYS (initstate, char *,
 _GL_CXXALIAS_SYS_CAST (initstate, char *,
                        (unsigned int seed, char *buf, size_t buf_size));
 # endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (initstate);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef initstate
 # if HAVE_RAW_DECL_INITSTATE
@@ -981,7 +1092,9 @@ _GL_FUNCDECL_SYS (setstate, char *, (char *arg_state) 
_GL_ARG_NONNULL ((1)));
    is                                     const char *arg_state.  */
 _GL_CXXALIAS_SYS_CAST (setstate, char *, (char *arg_state));
 # endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (setstate);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef setstate
 # if HAVE_RAW_DECL_SETSTATE
@@ -1167,7 +1280,9 @@ _GL_FUNCDECL_SYS (reallocarray, void *,
 _GL_CXXALIAS_SYS (reallocarray, void *,
                   (void *ptr, size_t nmemb, size_t size));
 # endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (reallocarray);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef reallocarray
 # if HAVE_RAW_DECL_REALLOCARRAY
diff --git a/lib/string.in.h b/lib/string.in.h
index b227a178873..aa088213927 100644
--- a/lib/string.in.h
+++ b/lib/string.in.h
@@ -308,16 +308,32 @@ _GL_WARN_ON_USE (memmem, "memmem is unportable and often 
quadratic - "
 /* Copy N bytes of SRC to DEST, return pointer to bytes after the
    last written byte.  */
 #if @GNULIB_MEMPCPY@
-# if ! @HAVE_MEMPCPY@
+# if @REPLACE_MEMPCPY@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef mempcpy
+#   define mempcpy rpl_mempcpy
+#  endif
+_GL_FUNCDECL_RPL (mempcpy, void *,
+                  (void *restrict __dest, void const *restrict __src,
+                   size_t __n)
+                  _GL_ARG_NONNULL ((1, 2)));
+_GL_CXXALIAS_RPL (mempcpy, void *,
+                  (void *restrict __dest, void const *restrict __src,
+                   size_t __n));
+# else
+#  if !@HAVE_MEMPCPY@
 _GL_FUNCDECL_SYS (mempcpy, void *,
                   (void *restrict __dest, void const *restrict __src,
                    size_t __n)
                   _GL_ARG_NONNULL ((1, 2)));
-# endif
+#  endif
 _GL_CXXALIAS_SYS (mempcpy, void *,
                   (void *restrict __dest, void const *restrict __src,
                    size_t __n));
+# endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (mempcpy);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef mempcpy
 # if HAVE_RAW_DECL_MEMPCPY
@@ -406,14 +422,28 @@ _GL_WARN_ON_USE (rawmemchr, "rawmemchr is unportable - "
 
 /* Copy SRC to DST, returning the address of the terminating '\0' in DST.  */
 #if @GNULIB_STPCPY@
-# if ! @HAVE_STPCPY@
+# if @REPLACE_STPCPY@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef stpcpy
+#   define stpcpy rpl_stpcpy
+#  endif
+_GL_FUNCDECL_RPL (stpcpy, char *,
+                  (char *restrict __dst, char const *restrict __src)
+                  _GL_ARG_NONNULL ((1, 2)));
+_GL_CXXALIAS_RPL (stpcpy, char *,
+                  (char *restrict __dst, char const *restrict __src));
+# else
+#  if !@HAVE_STPCPY@
 _GL_FUNCDECL_SYS (stpcpy, char *,
                   (char *restrict __dst, char const *restrict __src)
                   _GL_ARG_NONNULL ((1, 2)));
-# endif
+#  endif
 _GL_CXXALIAS_SYS (stpcpy, char *,
                   (char *restrict __dst, char const *restrict __src));
+# endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (stpcpy);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef stpcpy
 # if HAVE_RAW_DECL_STPCPY
@@ -448,7 +478,9 @@ _GL_CXXALIAS_SYS (stpncpy, char *,
                   (char *restrict __dst, char const *restrict __src,
                    size_t __n));
 # endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (stpncpy);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef stpncpy
 # if HAVE_RAW_DECL_STPNCPY
@@ -1212,7 +1244,7 @@ _GL_FUNCDECL_SYS (strerror_r, int, (int errnum, char 
*buf, size_t buflen)
 #  endif
 _GL_CXXALIAS_SYS (strerror_r, int, (int errnum, char *buf, size_t buflen));
 # endif
-# if @HAVE_DECL_STRERROR_R@
+# if __GLIBC__ >= 2 && @HAVE_DECL_STRERROR_R@
 _GL_CXXALIASWARN (strerror_r);
 # endif
 #elif defined GNULIB_POSIXCHECK
diff --git a/lib/sys_stat.in.h b/lib/sys_stat.in.h
index 096887c0162..0c2f39c12bf 100644
--- a/lib/sys_stat.in.h
+++ b/lib/sys_stat.in.h
@@ -549,7 +549,7 @@ _GL_FUNCDECL_SYS (futimens, int, (int fd, struct timespec 
const times[2]));
 #  endif
 _GL_CXXALIAS_SYS (futimens, int, (int fd, struct timespec const times[2]));
 # endif
-# if @HAVE_FUTIMENS@
+# if __GLIBC__ >= 2 && @HAVE_FUTIMENS@
 _GL_CXXALIASWARN (futimens);
 # endif
 #elif defined GNULIB_POSIXCHECK
@@ -716,7 +716,9 @@ _GL_FUNCDECL_SYS (mkfifoat, int, (int fd, char const *file, 
mode_t mode)
 #  endif
 _GL_CXXALIAS_SYS (mkfifoat, int, (int fd, char const *file, mode_t mode));
 # endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (mkfifoat);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef mkfifoat
 # if HAVE_RAW_DECL_MKFIFOAT
@@ -773,7 +775,9 @@ _GL_FUNCDECL_SYS (mknodat, int,
 _GL_CXXALIAS_SYS (mknodat, int,
                   (int fd, char const *file, mode_t mode, dev_t dev));
 # endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (mknodat);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef mknodat
 # if HAVE_RAW_DECL_MKNODAT
@@ -937,7 +941,7 @@ _GL_FUNCDECL_SYS (utimensat, int, (int fd, char const *name,
 _GL_CXXALIAS_SYS (utimensat, int, (int fd, char const *name,
                                    struct timespec const times[2], int flag));
 # endif
-# if @HAVE_UTIMENSAT@
+# if __GLIBC__ >= 2 && @HAVE_UTIMENSAT@
 _GL_CXXALIASWARN (utimensat);
 # endif
 #elif defined GNULIB_POSIXCHECK
diff --git a/lib/time.in.h b/lib/time.in.h
index 50c9b30b6b3..87cda21413b 100644
--- a/lib/time.in.h
+++ b/lib/time.in.h
@@ -112,12 +112,24 @@ struct __time_t_must_be_integral {
 /* Set *TS to the current time, and return BASE.
    Upon failure, return 0.  */
 # if @GNULIB_TIMESPEC_GET@
-#  if ! @HAVE_TIMESPEC_GET@
+#  if @REPLACE_TIMESPEC_GET@
+#   if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#    undef timespec_get
+#    define timespec_get rpl_timespec_get
+#   endif
+_GL_FUNCDECL_RPL (timespec_get, int, (struct timespec *ts, int base)
+                                     _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (timespec_get, int, (struct timespec *ts, int base));
+#  else
+#   if !@HAVE_TIMESPEC_GET@
 _GL_FUNCDECL_SYS (timespec_get, int, (struct timespec *ts, int base)
                                      _GL_ARG_NONNULL ((1)));
-#  endif
+#   endif
 _GL_CXXALIAS_SYS (timespec_get, int, (struct timespec *ts, int base));
+#  endif
+#  if __GLIBC__ >= 2
 _GL_CXXALIASWARN (timespec_get);
+#  endif
 # endif
 
 /* Set *TS to the current time resolution, and return BASE.
@@ -423,7 +435,9 @@ _GL_FUNCDECL_SYS (timegm, time_t, (struct tm *__tm) 
_GL_ARG_NONNULL ((1)));
 #   endif
 _GL_CXXALIAS_SYS (timegm, time_t, (struct tm *__tm));
 #  endif
+#  if __GLIBC__ >= 2
 _GL_CXXALIASWARN (timegm);
+#  endif
 # endif
 
 /* Encourage applications to avoid unsafe functions that can overrun
diff --git a/lib/unistd.in.h b/lib/unistd.in.h
index 4812fdb1120..bfc501e5a7d 100644
--- a/lib/unistd.in.h
+++ b/lib/unistd.in.h
@@ -541,17 +541,22 @@ _GL_CXXALIASWARN (dup2);
    Return newfd if successful, otherwise -1 and errno set.
    See the Linux man page at
    <https://www.kernel.org/doc/man-pages/online/pages/man2/dup3.2.html>.  */
-# if @HAVE_DUP3@
+# if @REPLACE_DUP3@
 #  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef dup3
 #   define dup3 rpl_dup3
 #  endif
 _GL_FUNCDECL_RPL (dup3, int, (int oldfd, int newfd, int flags));
 _GL_CXXALIAS_RPL (dup3, int, (int oldfd, int newfd, int flags));
 # else
+#  if !@HAVE_DUP3@
 _GL_FUNCDECL_SYS (dup3, int, (int oldfd, int newfd, int flags));
+#  endif
 _GL_CXXALIAS_SYS (dup3, int, (int oldfd, int newfd, int flags));
 # endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (dup3);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef dup3
 # if HAVE_RAW_DECL_DUP3
@@ -870,7 +875,9 @@ _GL_FUNCDECL_SYS (execvpe, int,
 _GL_CXXALIAS_SYS (execvpe, int,
                   (const char *program, char * const *argv, char * const 
*env));
 # endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (execvpe);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef execvpe
 # if HAVE_RAW_DECL_EXECVPE
@@ -925,7 +932,9 @@ _GL_FUNCDECL_SYS (faccessat, int,
 _GL_CXXALIAS_SYS (faccessat, int,
                   (int fd, char const *file, int mode, int flag));
 # endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (faccessat);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef faccessat
 # if HAVE_RAW_DECL_FACCESSAT
@@ -1002,11 +1011,22 @@ _GL_WARN_ON_USE (fchownat, "fchownat is not portable - "
    Return 0 if successful, otherwise -1 and errno set.
    See POSIX:2008 specification
    
<https://pubs.opengroup.org/onlinepubs/9699919799/functions/fdatasync.html>.  */
-# if !@HAVE_FDATASYNC@ || !@HAVE_DECL_FDATASYNC@
+# if @REPLACE_FDATASYNC@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef fdatasync
+#   define fdatasync rpl_fdatasync
+#  endif
+_GL_FUNCDECL_RPL (fdatasync, int, (int fd));
+_GL_CXXALIAS_RPL (fdatasync, int, (int fd));
+# else
+#  if !@HAVE_FDATASYNC@|| !@HAVE_DECL_FDATASYNC@
 _GL_FUNCDECL_SYS (fdatasync, int, (int fd));
-# endif
+#  endif
 _GL_CXXALIAS_SYS (fdatasync, int, (int fd));
+# endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (fdatasync);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef fdatasync
 # if HAVE_RAW_DECL_FDATASYNC
@@ -1053,7 +1073,9 @@ _GL_FUNCDECL_SYS (ftruncate, int, (int fd, off_t length));
 #  endif
 _GL_CXXALIAS_SYS (ftruncate, int, (int fd, off_t length));
 # endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (ftruncate);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef ftruncate
 # if HAVE_RAW_DECL_FTRUNCATE
@@ -1185,11 +1207,22 @@ _GL_WARN_ON_USE (getdtablesize, "getdtablesize is 
unportable - "
 
 #if @GNULIB_GETENTROPY@
 /* Fill a buffer with random bytes.  */
-# if !@HAVE_GETENTROPY@
+# if @REPLACE_GETENTROPY@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef getentropy
+#   define getentropy rpl_getentropy
+#  endif
+_GL_FUNCDECL_RPL (getentropy, int, (void *buffer, size_t length));
+_GL_CXXALIAS_RPL (getentropy, int, (void *buffer, size_t length));
+# else
+#  if !@HAVE_GETENTROPY@
 _GL_FUNCDECL_SYS (getentropy, int, (void *buffer, size_t length));
-# endif
+#  endif
 _GL_CXXALIAS_SYS (getentropy, int, (void *buffer, size_t length));
+# endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (getentropy);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef getentropy
 # if HAVE_RAW_DECL_GETENTROPY
@@ -1323,7 +1356,9 @@ _GL_FUNCDECL_SYS (getlogin_r, int, (char *name, size_t 
size)
                                                      int size.  */
 _GL_CXXALIAS_SYS_CAST (getlogin_r, int, (char *name, size_t size));
 # endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (getlogin_r);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef getlogin_r
 # if HAVE_RAW_DECL_GETLOGIN_R
@@ -1661,7 +1696,9 @@ _GL_CXXALIAS_SYS (linkat, int,
                   (int fd1, const char *path1, int fd2, const char *path2,
                    int flag));
 # endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (linkat);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef linkat
 # if HAVE_RAW_DECL_LINKAT
@@ -1742,8 +1779,9 @@ _GL_WARN_ON_USE (pipe, "pipe is unportable - "
    Return 0 upon success, or -1 with errno set upon failure.
    See also the Linux man page at
    <https://www.kernel.org/doc/man-pages/online/pages/man2/pipe2.2.html>.  */
-# if @HAVE_PIPE2@
+# if @REPLACE_PIPE2@
 #  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef pipe2
 #   define pipe2 rpl_pipe2
 #  endif
 _GL_FUNCDECL_RPL (pipe2, int, (int fd[2], int flags) _GL_ARG_NONNULL ((1)));
@@ -1752,7 +1790,9 @@ _GL_CXXALIAS_RPL (pipe2, int, (int fd[2], int flags));
 _GL_FUNCDECL_SYS (pipe2, int, (int fd[2], int flags) _GL_ARG_NONNULL ((1)));
 _GL_CXXALIAS_SYS (pipe2, int, (int fd[2], int flags));
 # endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (pipe2);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef pipe2
 # if HAVE_RAW_DECL_PIPE2
@@ -1787,7 +1827,9 @@ _GL_FUNCDECL_SYS (pread, ssize_t,
 _GL_CXXALIAS_SYS (pread, ssize_t,
                   (int fd, void *buf, size_t bufsize, off_t offset));
 # endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (pread);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef pread
 # if HAVE_RAW_DECL_PREAD
@@ -1822,7 +1864,9 @@ _GL_FUNCDECL_SYS (pwrite, ssize_t,
 _GL_CXXALIAS_SYS (pwrite, ssize_t,
                   (int fd, const void *buf, size_t bufsize, off_t offset));
 # endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (pwrite);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef pwrite
 # if HAVE_RAW_DECL_PWRITE
@@ -1936,7 +1980,9 @@ _GL_CXXALIAS_SYS (readlinkat, ssize_t,
                   (int fd, char const *restrict file,
                    char *restrict buf, size_t len));
 # endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (readlinkat);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef readlinkat
 # if HAVE_RAW_DECL_READLINKAT
@@ -1996,15 +2042,27 @@ _GL_CXXALIASWARN (rmdir);
 
    Platforms with no ability to set the hostname return -1 and set
    errno = ENOSYS.  */
-# if !@HAVE_SETHOSTNAME@ || !@HAVE_DECL_SETHOSTNAME@
+# if @REPLACE_SETHOSTNAME@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef sethostname
+#   define sethostname rpl_sethostname
+#  endif
+_GL_FUNCDECL_RPL (sethostname, int, (const char *name, size_t len)
+                                    _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (sethostname, int, (const char *name, size_t len));
+# else
+#  if !@HAVE_SETHOSTNAME@ || !@HAVE_DECL_SETHOSTNAME@
 _GL_FUNCDECL_SYS (sethostname, int, (const char *name, size_t len)
                                     _GL_ARG_NONNULL ((1)));
-# endif
+#  endif
 /* Need to cast, because on Solaris 11 2011-10, Mac OS X 10.5, IRIX 6.5
    and FreeBSD 6.4 the second parameter is int.  On Solaris 11
    2011-10, the first parameter is not const.  */
 _GL_CXXALIAS_SYS_CAST (sethostname, int, (const char *name, size_t len));
+# endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (sethostname);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef sethostname
 # if HAVE_RAW_DECL_SETHOSTNAME
@@ -2113,7 +2171,9 @@ _GL_FUNCDECL_SYS (symlinkat, int,
 _GL_CXXALIAS_SYS (symlinkat, int,
                   (char const *contents, int fd, char const *file));
 # endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (symlinkat);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef symlinkat
 # if HAVE_RAW_DECL_SYMLINKAT
@@ -2143,7 +2203,9 @@ _GL_FUNCDECL_SYS (truncate, int, (const char *filename, 
off_t length)
 #  endif
 _GL_CXXALIAS_SYS (truncate, int, (const char *filename, off_t length));
 # endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (truncate);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef truncate
 # if HAVE_RAW_DECL_TRUNCATE
@@ -2173,7 +2235,9 @@ _GL_FUNCDECL_SYS (ttyname_r, int,
 _GL_CXXALIAS_SYS (ttyname_r, int,
                   (int fd, char *buf, size_t buflen));
 # endif
+# if __GLIBC__ >= 2
 _GL_CXXALIASWARN (ttyname_r);
+# endif
 #elif defined GNULIB_POSIXCHECK
 # undef ttyname_r
 # if HAVE_RAW_DECL_TTYNAME_R
diff --git a/lib/verify.h b/lib/verify.h
index b63cb264321..8f786af7f5a 100644
--- a/lib/verify.h
+++ b/lib/verify.h
@@ -222,7 +222,21 @@ template <int w>
 
 /* _GL_STATIC_ASSERT_H is defined if this code is copied into assert.h.  */
 #ifdef _GL_STATIC_ASSERT_H
-# if !defined _GL_HAVE__STATIC_ASSERT1 && !defined _Static_assert
+/* Define _Static_assert if needed.  */
+/* With clang ≥ 3.8.0 in C++ mode, _Static_assert already works and accepts
+   1 or 2 arguments.  We better don't override it, because clang's standard
+   C++ library uses static_assert inside classes in several places, and our
+   replacement via _GL_VERIFY does not work in these contexts.  */
+# if (defined __cplusplus && defined __clang__ \
+      && (4 <= __clang_major__ + (8 <= __clang_minor__)))
+#  if 5 <= __clang_major__
+/* Avoid "warning: 'static_assert' with no message is a C++17 extension".  */
+#   pragma clang diagnostic ignored "-Wc++17-extensions"
+#  else
+/* Avoid "warning: static_assert with no message is a C++1z extension".  */
+#   pragma clang diagnostic ignored "-Wc++1z-extensions"
+#  endif
+# elif !defined _GL_HAVE__STATIC_ASSERT1 && !defined _Static_assert
 #  if !defined _MSC_VER || defined __clang__
 #   define _Static_assert(...) \
       _GL_VERIFY (__VA_ARGS__, "static assertion failed", -)
@@ -233,6 +247,7 @@ template <int w>
       _GL_VERIFY ((R), "static assertion failed", -)
 #  endif
 # endif
+/* Define static_assert if needed.  */
 # if (!defined static_assert \
       && __STDC_VERSION__ < 202311 \
       && (!defined __cplusplus \
diff --git a/lisp/bindings.el b/lisp/bindings.el
index 99189d2e570..c77b64c05da 100644
--- a/lisp/bindings.el
+++ b/lisp/bindings.el
@@ -1011,7 +1011,7 @@ if `inhibit-field-text-motion' is non-nil."
 ;; no idea whereas to bind it.  Any suggestion welcome.  -stef
 ;; (define-key ctl-x-map "U" 'undo-only)
 (defvar-keymap undo-repeat-map
-  :doc "Keymap to repeat undo key sequences \\`C-x u u'.  Used in 
`repeat-mode'."
+  :doc "Keymap to repeat `undo' commands.  Used in `repeat-mode'."
   :repeat t
   "u" #'undo)
 
@@ -1108,7 +1108,7 @@ if `inhibit-field-text-motion' is non-nil."
 (define-key ctl-x-map "`" 'next-error)
 
 (defvar-keymap next-error-repeat-map
-  :doc "Keymap to repeat `next-error' key sequences.  Used in `repeat-mode'."
+  :doc "Keymap to repeat `next-error' and `previous-error'.  Used in 
`repeat-mode'."
   :repeat t
   "n"   #'next-error
   "M-n" #'next-error
@@ -1470,7 +1470,7 @@ if `inhibit-field-text-motion' is non-nil."
 (define-key ctl-x-map "]" 'forward-page)
 
 (defvar-keymap page-navigation-repeat-map
-  :doc "Keymap to repeat page navigation key sequences.  Used in 
`repeat-mode'."
+  :doc "Keymap to repeat `forward-page' and `backward-page'.  Used in 
`repeat-mode'."
   :repeat t
   "]" #'forward-page
   "[" #'backward-page)
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index b1a46d520e6..e0c769c7e60 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -72,34 +72,40 @@
 (require 'macroexp)
 (eval-when-compile (require 'subr-x))
 
+(defun bytecomp--log-lap-arg (arg)
+  ;; Convert an argument that may be a LAP operation to something printable.
+  (cond
+   ;; Symbols are just stripped of their -byte prefix if any.
+   ((symbolp arg)
+    (intern (string-remove-prefix "byte-" (symbol-name arg))))
+   ;; Conses are assumed to be LAP ops or tags.
+   ((and (consp arg) (symbolp (car arg)))
+    (let* ((head (car arg))
+           (tail (cdr arg))
+           (op (intern (string-remove-prefix "byte-" (symbol-name head)))))
+      (cond
+       ((eq head 'TAG)
+        (format "%d:" (car tail)))
+       ((memq head byte-goto-ops)
+        (format "(%s %d)" op (cadr tail)))
+       ((memq head byte-constref-ops)
+        (format "(%s %s)"
+                (if (eq op 'constant) 'const op)
+                (if (numberp tail)
+                    (format "<V%d>" tail)     ; closure var reference
+                  (format "%S" (car tail))))) ; actual constant
+       ;; Ops with an immediate argument.
+       ((memq op '( stack-ref stack-set call unbind
+                    listN concatN insertN discardN discardN-preserve-tos))
+        (format "(%s %S)" op tail))
+       ;; Without immediate, print just the symbol.
+       (t op))))
+   ;; Anything else is printed as-is.
+   (t arg)))
+
 (defun byte-compile-log-lap-1 (format &rest args)
   (byte-compile-log-1
-   (apply #'format-message format
-     (let (c a)
-       (mapcar (lambda (arg)
-                 (if (not (consp arg))
-                     (if (and (symbolp arg)
-                              (string-match "^byte-" (symbol-name arg)))
-                         (intern (substring (symbol-name arg) 5))
-                       arg)
-                   (if (integerp (setq c (car arg)))
-                        (error "Non-symbolic byte-op %s" c))
-                   (if (eq c 'TAG)
-                       (setq c arg)
-                     (setq a (cond ((memq c byte-goto-ops)
-                                    (car (cdr (cdr arg))))
-                                   ((memq c byte-constref-ops)
-                                    (car (cdr arg)))
-                                   (t (cdr arg))))
-                     (setq c (symbol-name c))
-                     (if (string-match "^byte-." c)
-                         (setq c (intern (substring c 5)))))
-                   (if (eq c 'constant) (setq c 'const))
-                   (if (and (eq (cdr arg) 0)
-                            (not (memq c '(unbind call const))))
-                       c
-                     (format "(%s %s)" c a))))
-              args)))))
+   (apply #'format-message format (mapcar #'bytecomp--log-lap-arg args))))
 
 (defmacro byte-compile-log-lap (format-string &rest args)
   `(and (memq byte-optimize-log '(t byte))
@@ -975,6 +981,43 @@ for speeding up processing.")
    (t ;; Moving the constant to the end can enable some lapcode optimizations.
     (list (car form) (nth 2 form) (nth 1 form)))))
 
+(defun byte-opt--nary-comparison (form)
+  "Optimise n-ary comparisons such as `=', `<' etc."
+  (let ((nargs (length (cdr form))))
+    (cond
+     ((= nargs 1)
+      `(progn (cadr form) t))
+     ((>= nargs 3)
+      ;; At least 3 arguments: transform to N-1 binary comparisons,
+      ;; since those have their own byte-ops which are particularly
+      ;; fast for fixnums.
+      (let* ((op (car form))
+             (bindings nil)
+             (rev-args nil))
+        (if (memq nil (mapcar #'macroexp-copyable-p (cddr form)))
+            ;; At least one arg beyond the first is non-constant non-variable:
+            ;; create temporaries for all args to guard against side-effects.
+            ;; The optimiser will eliminate trivial bindings later.
+            (let ((i 1))
+              (dolist (arg (cdr form))
+                (let ((var (make-symbol (format "arg%d" i))))
+                  (push var rev-args)
+                  (push (list var arg) bindings)
+                  (setq i (1+ i)))))
+          ;; All args beyond the first are copyable: no temporary variables
+          ;; required.
+          (setq rev-args (reverse (cdr form))))
+        (let ((prev (car rev-args))
+              (exprs nil))
+          (dolist (arg (cdr rev-args))
+            (push (list op arg prev) exprs)
+            (setq prev arg))
+          (let ((and-expr (cons 'and exprs)))
+            (if bindings
+                (list 'let (nreverse bindings) and-expr)
+              and-expr)))))
+     (t form))))
+
 (defun byte-optimize-constant-args (form)
   (let ((ok t)
        (rest (cdr form)))
@@ -1130,13 +1173,18 @@ See Info node `(elisp) Integer Basics'."
 (put 'max 'byte-optimizer #'byte-optimize-min-max)
 (put 'min 'byte-optimizer #'byte-optimize-min-max)
 
-(put '=   'byte-optimizer #'byte-optimize-binary-predicate)
 (put 'eq  'byte-optimizer #'byte-optimize-eq)
 (put 'eql   'byte-optimizer #'byte-optimize-equal)
 (put 'equal 'byte-optimizer #'byte-optimize-equal)
 (put 'string= 'byte-optimizer #'byte-optimize-binary-predicate)
 (put 'string-equal 'byte-optimizer #'byte-optimize-binary-predicate)
 
+(put '=  'byte-optimizer #'byte-opt--nary-comparison)
+(put '<  'byte-optimizer #'byte-opt--nary-comparison)
+(put '<= 'byte-optimizer #'byte-opt--nary-comparison)
+(put '>  'byte-optimizer #'byte-opt--nary-comparison)
+(put '>= 'byte-optimizer #'byte-opt--nary-comparison)
+
 (put 'string-greaterp 'byte-optimizer #'byte-optimize-string-greaterp)
 (put 'string> 'byte-optimizer #'byte-optimize-string-greaterp)
 
@@ -1908,6 +1956,7 @@ See Info node `(elisp) Integer Basics'."
 
 (defconst byte-after-unbind-ops
    '(byte-constant byte-dup byte-stack-ref byte-stack-set byte-discard
+     byte-discardN byte-discardN-preserve-tos
      byte-symbolp byte-consp byte-stringp byte-listp byte-numberp byte-integerp
      byte-eq byte-not
      byte-cons byte-list1 byte-list2 byte-list3 byte-list4 byte-listN
@@ -1971,568 +2020,678 @@ See Info node `(elisp) Integer Basics'."
 (defun byte-optimize-lapcode (lap &optional _for-effect)
   "Simple peephole optimizer.  LAP is both modified and returned.
 If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
-  (let (lap0
-       lap1
-       lap2
-       (keep-going 'first-time)
-       (add-depth 0)
-       rest tmp tmp2 tmp3
-       (side-effect-free (if byte-compile-delete-errors
+  (let ((side-effect-free (if byte-compile-delete-errors
                              byte-compile-side-effect-free-ops
-                           byte-compile-side-effect-and-error-free-ops)))
+                           byte-compile-side-effect-and-error-free-ops))
+       (add-depth 0)
+       (keep-going 'first-time)
+        ;; Create a cons cell as head of the list so that removing the first
+        ;; element does not need special-casing: `setcdr' always works.
+        (lap-head (cons nil lap)))
     (while keep-going
-      (or (eq keep-going 'first-time)
-         (byte-compile-log-lap "  ---- next pass"))
-      (setq rest lap
-           keep-going nil)
-      (while rest
-       (setq lap0 (car rest)
-             lap1 (nth 1 rest)
-             lap2 (nth 2 rest))
-
-       ;; You may notice that sequences like "dup varset discard" are
-       ;; optimized but sequences like "dup varset TAG1: discard" are not.
-       ;; You may be tempted to change this; resist that temptation.
-       (cond
-        ;; <side-effect-free> pop -->  <deleted>
-        ;;  ...including:
-        ;; const-X pop   -->  <deleted>
-        ;; varref-X pop  -->  <deleted>
-        ;; dup pop       -->  <deleted>
-        ;;
-        ((and (eq 'byte-discard (car lap1))
-              (memq (car lap0) side-effect-free))
-         (setq keep-going t)
-         (setq tmp (aref byte-stack+-info (symbol-value (car lap0))))
-         (setq rest (cdr rest))
-         (cond ((eql tmp 1)
-                (byte-compile-log-lap
-                 "  %s discard\t-->\t<deleted>" lap0)
-                (setq lap (delq lap0 (delq lap1 lap))))
-               ((eql tmp 0)
-                (byte-compile-log-lap
-                 "  %s discard\t-->\t<deleted> discard" lap0)
-                (setq lap (delq lap0 lap)))
-               ((eql tmp -1)
-                (byte-compile-log-lap
-                 "  %s discard\t-->\tdiscard discard" lap0)
-                (setcar lap0 'byte-discard)
-                (setcdr lap0 0))
-               (t (error "Optimizer error: too much on the stack"))))
-        ;;
-        ;; goto*-X X:  -->  X:
-        ;;
-        ((and (memq (car lap0) byte-goto-ops)
-              (eq (cdr lap0) lap1))
-         (cond ((eq (car lap0) 'byte-goto)
-                (setq lap (delq lap0 lap))
-                (setq tmp "<deleted>"))
-               ((memq (car lap0) byte-goto-always-pop-ops)
-                (setcar lap0 (setq tmp 'byte-discard))
-                (setcdr lap0 0))
-               ((error "Depth conflict at tag %d" (nth 2 lap0))))
-         (and (memq byte-optimize-log '(t byte))
-              (byte-compile-log "  (goto %s) %s:\t-->\t%s %s:"
-                                (nth 1 lap1) (nth 1 lap1)
-                                tmp (nth 1 lap1)))
-         (setq keep-going t))
-        ;;
-        ;; varset-X varref-X  -->  dup varset-X
-        ;; varbind-X varref-X  -->  dup varbind-X
-        ;; const/dup varset-X varref-X --> const/dup varset-X const/dup
-        ;; const/dup varbind-X varref-X --> const/dup varbind-X const/dup
-        ;; The latter two can enable other optimizations.
-        ;;
-         ;; For lexical variables, we could do the same
-         ;;   stack-set-X+1 stack-ref-X  -->  dup stack-set-X+2
-         ;; but this is a very minor gain, since dup is stack-ref-0,
-         ;; i.e. it's only better if X>5, and even then it comes
-         ;; at the cost of an extra stack slot.  Let's not bother.
-        ((and (eq 'byte-varref (car lap2))
-               (eq (cdr lap1) (cdr lap2))
-               (memq (car lap1) '(byte-varset byte-varbind)))
-         (if (and (setq tmp (memq (car (cdr lap2)) byte-boolean-vars))
-                  (not (eq (car lap0) 'byte-constant)))
-             nil
-           (setq keep-going t)
-            (if (memq (car lap0) '(byte-constant byte-dup))
-                (progn
-                  (setq tmp (if (or (not tmp)
-                                    (macroexp--const-symbol-p
-                                     (car (cdr lap0))))
-                                (cdr lap0)
-                              (byte-compile-get-constant t)))
-                 (byte-compile-log-lap "  %s %s %s\t-->\t%s %s %s"
-                                       lap0 lap1 lap2 lap0 lap1
-                                       (cons (car lap0) tmp))
-                 (setcar lap2 (car lap0))
-                 (setcdr lap2 tmp))
-             (byte-compile-log-lap "  %s %s\t-->\tdup %s" lap1 lap2 lap1)
-             (setcar lap2 (car lap1))
-             (setcar lap1 'byte-dup)
-             (setcdr lap1 0)
-             ;; The stack depth gets locally increased, so we will
-             ;; increase maxdepth in case depth = maxdepth here.
-             ;; This can cause the third argument to byte-code to
-             ;; be larger than necessary.
-             (setq add-depth 1))))
-        ;;
-        ;; dup varset-X discard  -->  varset-X
-        ;; dup varbind-X discard  -->  varbind-X
-         ;; dup stack-set-X discard  -->  stack-set-X-1
-        ;; (the varbind variant can emerge from other optimizations)
-        ;;
-        ((and (eq 'byte-dup (car lap0))
-              (eq 'byte-discard (car lap2))
-              (memq (car lap1) '(byte-varset byte-varbind
-                                  byte-stack-set)))
-         (byte-compile-log-lap "  dup %s discard\t-->\t%s" lap1 lap1)
-         (setq keep-going t
-               rest (cdr rest))
-          (if (eq 'byte-stack-set (car lap1)) (cl-decf (cdr lap1)))
-         (setq lap (delq lap0 (delq lap2 lap))))
-        ;;
-        ;; not goto-X-if-nil              -->  goto-X-if-non-nil
-        ;; not goto-X-if-non-nil          -->  goto-X-if-nil
-        ;;
-        ;; it is wrong to do the same thing for the -else-pop variants.
-        ;;
-        ((and (eq 'byte-not (car lap0))
-              (memq (car lap1) '(byte-goto-if-nil byte-goto-if-not-nil)))
-         (byte-compile-log-lap "  not %s\t-->\t%s"
-                               lap1
-                               (cons
-                                (if (eq (car lap1) 'byte-goto-if-nil)
-                                    'byte-goto-if-not-nil
-                                  'byte-goto-if-nil)
-                                (cdr lap1)))
-         (setcar lap1 (if (eq (car lap1) 'byte-goto-if-nil)
-                          'byte-goto-if-not-nil
-                        'byte-goto-if-nil))
-         (setq lap (delq lap0 lap))
-         (setq keep-going t))
-        ;;
-        ;; goto-X-if-nil     goto-Y X:  -->  goto-Y-if-non-nil X:
-        ;; goto-X-if-non-nil goto-Y X:  -->  goto-Y-if-nil     X:
-        ;;
-        ;; it is wrong to do the same thing for the -else-pop variants.
-        ;;
-        ((and (memq (car lap0)
-                     '(byte-goto-if-nil byte-goto-if-not-nil)) ; gotoX
-              (eq 'byte-goto (car lap1))                      ; gotoY
-              (eq (cdr lap0) lap2))                           ; TAG X
-         (let ((inverse (if (eq 'byte-goto-if-nil (car lap0))
-                            'byte-goto-if-not-nil 'byte-goto-if-nil)))
-           (byte-compile-log-lap "  %s %s %s:\t-->\t%s %s:"
-                                 lap0 lap1 lap2
-                                 (cons inverse (cdr lap1)) lap2)
-           (setq lap (delq lap0 lap))
-           (setcar lap1 inverse)
-           (setq keep-going t)))
-        ;;
-        ;; const goto-if-* --> whatever
-        ;;
-        ((and (eq 'byte-constant (car lap0))
-              (memq (car lap1) byte-conditional-ops)
-               ;; If the `byte-constant's cdr is not a cons cell, it has
-               ;; to be an index into the constant pool); even though
-               ;; it'll be a constant, that constant is not known yet
-               ;; (it's typically a free variable of a closure, so will
-               ;; only be known when the closure will be built at
-               ;; run-time).
-               (consp (cdr lap0)))
-         (cond ((if (memq (car lap1) '(byte-goto-if-nil
-                                        byte-goto-if-nil-else-pop))
-                     (car (cdr lap0))
-                   (not (car (cdr lap0))))
-                (byte-compile-log-lap "  %s %s\t-->\t<deleted>"
-                                      lap0 lap1)
-                (setq rest (cdr rest)
-                      lap (delq lap0 (delq lap1 lap))))
-               (t
-                (byte-compile-log-lap "  %s %s\t-->\t%s"
-                                      lap0 lap1
-                                      (cons 'byte-goto (cdr lap1)))
-                (when (memq (car lap1) byte-goto-always-pop-ops)
-                  (setq lap (delq lap0 lap)))
-                (setcar lap1 'byte-goto)))
-          (setq keep-going t))
-        ;;
-        ;; varref-X varref-X  -->  varref-X dup
-        ;; varref-X [dup ...] varref-X  -->  varref-X [dup ...] dup
-        ;; stackref-X [dup ...] stackref-X+N --> stackref-X [dup ...] dup
-        ;; We don't optimize the const-X variations on this here,
-        ;; because that would inhibit some goto optimizations; we
-        ;; optimize the const-X case after all other optimizations.
-        ;;
-        ((and (memq (car lap0) '(byte-varref byte-stack-ref))
-              (progn
-                (setq tmp (cdr rest))
-                 (setq tmp2 0)
-                (while (eq (car (car tmp)) 'byte-dup)
-                  (setq tmp2 (1+ tmp2))
-                   (setq tmp (cdr tmp)))
-                t)
-              (eq (if (eq 'byte-stack-ref (car lap0))
-                       (+ tmp2 1 (cdr lap0))
-                     (cdr lap0))
-                   (cdr (car tmp)))
-              (eq (car lap0) (car (car tmp))))
-         (if (memq byte-optimize-log '(t byte))
-             (let ((str ""))
-               (setq tmp2 (cdr rest))
-               (while (not (eq tmp tmp2))
-                 (setq tmp2 (cdr tmp2)
-                       str (concat str " dup")))
-               (byte-compile-log-lap "  %s%s %s\t-->\t%s%s dup"
-                                     lap0 str lap0 lap0 str)))
-         (setq keep-going t)
-         (setcar (car tmp) 'byte-dup)
-         (setcdr (car tmp) 0)
-         (setq rest tmp))
-        ;;
-        ;; TAG1: TAG2: --> TAG1: <deleted>
-        ;; (and other references to TAG2 are replaced with TAG1)
-        ;;
-        ((and (eq (car lap0) 'TAG)
-              (eq (car lap1) 'TAG))
-         (and (memq byte-optimize-log '(t byte))
-              (byte-compile-log "  adjacent tags %d and %d merged"
-                                (nth 1 lap1) (nth 1 lap0)))
-         (setq tmp3 lap)
-         (while (setq tmp2 (rassq lap0 tmp3))
-           (setcdr tmp2 lap1)
-           (setq tmp3 (cdr (memq tmp2 tmp3))))
-         (setq lap (delq lap0 lap)
-               keep-going t)
-          ;; replace references to tag in jump tables, if any
-          (dolist (table byte-compile-jump-tables)
-            (maphash #'(lambda (value tag)
-                         (when (equal tag lap0)
-                           (puthash value lap1 table)))
-                     table)))
-        ;;
-        ;; unused-TAG: --> <deleted>
-        ;;
-        ((and (eq 'TAG (car lap0))
-              (not (rassq lap0 lap))
-               ;; make sure this tag isn't used in a jump-table
-               (cl-loop for table in byte-compile-jump-tables
-                        when (member lap0 (hash-table-values table))
-                        return nil finally return t))
-         (and (memq byte-optimize-log '(t byte))
-              (byte-compile-log "  unused tag %d removed" (nth 1 lap0)))
-         (setq lap (delq lap0 lap)
-               keep-going t))
-        ;;
-        ;; goto   ... --> goto   <delete until TAG or end>
-        ;; return ... --> return <delete until TAG or end>
-         ;;
-        ((and (memq (car lap0) '(byte-goto byte-return))
-              (not (memq (car lap1) '(TAG nil))))
-         (setq tmp rest)
-         (let ((i 0)
-               (opt-p (memq byte-optimize-log '(t byte)))
-               str deleted)
-           (while (and (setq tmp (cdr tmp))
-                       (not (eq 'TAG (car (car tmp)))))
-             (if opt-p (setq deleted (cons (car tmp) deleted)
-                             str (concat str " %s")
-                             i (1+ i))))
-           (if opt-p
-               (let ((tagstr
-                      (if (eq 'TAG (car (car tmp)))
-                          (format "%d:" (car (cdr (car tmp))))
-                        (or (car tmp) ""))))
-                 (if (< i 6)
-                     (apply 'byte-compile-log-lap-1
-                            (concat "  %s" str
-                                    " %s\t-->\t%s <deleted> %s")
-                            lap0
-                            (nconc (nreverse deleted)
-                                   (list tagstr lap0 tagstr)))
-                   (byte-compile-log-lap
-                    "  %s <%d unreachable op%s> %s\t-->\t%s <deleted> %s"
-                    lap0 i (if (= i 1) "" "s")
-                    tagstr lap0 tagstr))))
-           (rplacd rest tmp))
-         (setq keep-going t))
-        ;;
-        ;; <safe-op> unbind --> unbind <safe-op>
-        ;; (this may enable other optimizations.)
-        ;;
-        ((and (eq 'byte-unbind (car lap1))
-              (memq (car lap0) byte-after-unbind-ops))
-         (byte-compile-log-lap "  %s %s\t-->\t%s %s" lap0 lap1 lap1 lap0)
-         (setcar rest lap1)
-         (setcar (cdr rest) lap0)
-         (setq keep-going t))
-        ;;
-        ;; varbind-X unbind-N            -->  discard unbind-(N-1)
-        ;; save-excursion unbind-N       -->  unbind-(N-1)
-        ;; save-restriction unbind-N     -->  unbind-(N-1)
-        ;; save-current-buffer unbind-N  -->  unbind-(N-1)
-        ;;
-        ((and (eq 'byte-unbind (car lap1))
-              (memq (car lap0) '(byte-varbind byte-save-excursion
-                                 byte-save-restriction
-                                  byte-save-current-buffer))
-              (< 0 (cdr lap1)))
-         (if (zerop (setcdr lap1 (1- (cdr lap1))))
-             (delq lap1 rest))
-         (if (eq (car lap0) 'byte-varbind)
-             (setcar rest (cons 'byte-discard 0))
-           (setq lap (delq lap0 lap)))
-         (byte-compile-log-lap "  %s %s\t-->\t%s %s"
-                               lap0 (cons (car lap1) (1+ (cdr lap1)))
-                               (if (eq (car lap0) 'byte-varbind)
-                                   (car rest)
-                                 (car (cdr rest)))
-                               (if (and (/= 0 (cdr lap1))
-                                        (eq (car lap0) 'byte-varbind))
-                                   (car (cdr rest))
-                                 ""))
-         (setq keep-going t))
-        ;;
-        ;; goto*-X ... X: goto-Y  --> goto*-Y
-        ;; goto-X ...  X: return  --> return
-        ;;
-        ((and (memq (car lap0) byte-goto-ops)
-              (memq (car (setq tmp (nth 1 (memq (cdr lap0) lap))))
-                    '(byte-goto byte-return)))
-         (cond ((and (or (eq (car lap0) 'byte-goto)
-                         (eq (car tmp) 'byte-goto))
-                      (not (eq (cdr tmp) (cdr lap0))))
-                (byte-compile-log-lap "  %s [%s]\t-->\t%s"
-                                      (car lap0) tmp tmp)
-                (if (eq (car tmp) 'byte-return)
-                    (setcar lap0 'byte-return))
-                (setcdr lap0 (cdr tmp))
-                (setq keep-going t))))
-        ;;
-        ;; goto-*-else-pop X ... X: goto-if-* --> whatever
-        ;; goto-*-else-pop X ... X: discard --> whatever
-        ;;
-        ((and (memq (car lap0) '(byte-goto-if-nil-else-pop
-                                 byte-goto-if-not-nil-else-pop))
-              (memq (car (car (setq tmp (cdr (memq (cdr lap0) lap)))))
-                    (eval-when-compile
-                      (cons 'byte-discard byte-conditional-ops)))
-              (not (eq lap0 (car tmp))))
-         (setq tmp2 (car tmp))
-         (setq tmp3 (assq (car lap0) '((byte-goto-if-nil-else-pop
-                                        byte-goto-if-nil)
-                                       (byte-goto-if-not-nil-else-pop
-                                        byte-goto-if-not-nil))))
-         (if (memq (car tmp2) tmp3)
-             (progn (setcar lap0 (car tmp2))
-                    (setcdr lap0 (cdr tmp2))
-                    (byte-compile-log-lap "  %s-else-pop [%s]\t-->\t%s"
-                                          (car lap0) tmp2 lap0))
-           ;; Get rid of the -else-pop's and jump one step further.
-           (or (eq 'TAG (car (nth 1 tmp)))
-               (setcdr tmp (cons (byte-compile-make-tag)
-                                 (cdr tmp))))
-           (byte-compile-log-lap "  %s [%s]\t-->\t%s <skip>"
-                                 (car lap0) tmp2 (nth 1 tmp3))
-           (setcar lap0 (nth 1 tmp3))
-           (setcdr lap0 (nth 1 tmp)))
-         (setq keep-going t))
-        ;;
-        ;; const goto-X ... X: goto-if-* --> whatever
-        ;; const goto-X ... X: discard   --> whatever
-        ;;
-        ((and (eq (car lap0) 'byte-constant)
-              (eq (car lap1) 'byte-goto)
-              (memq (car (car (setq tmp (cdr (memq (cdr lap1) lap)))))
-                    (eval-when-compile
-                      (cons 'byte-discard byte-conditional-ops)))
-              (not (eq lap1 (car tmp))))
-         (setq tmp2 (car tmp))
-         (cond ((when (consp (cdr lap0))
-                  (memq (car tmp2)
-                        (if (null (car (cdr lap0)))
-                            '(byte-goto-if-nil byte-goto-if-nil-else-pop)
-                          '(byte-goto-if-not-nil
-                            byte-goto-if-not-nil-else-pop))))
-                (byte-compile-log-lap "  %s goto [%s]\t-->\t%s %s"
-                                      lap0 tmp2 lap0 tmp2)
-                (setcar lap1 (car tmp2))
-                (setcdr lap1 (cdr tmp2))
-                ;; Let next step fix the (const,goto-if*) sequence.
-                (setq rest (cons nil rest))
-                (setq keep-going t))
-               ((or (consp (cdr lap0))
-                    (eq (car tmp2) 'byte-discard))
-                ;; Jump one step further
-                (byte-compile-log-lap
-                 "  %s goto [%s]\t-->\t<deleted> goto <skip>"
-                 lap0 tmp2)
-                (or (eq 'TAG (car (nth 1 tmp)))
-                    (setcdr tmp (cons (byte-compile-make-tag)
-                                      (cdr tmp))))
-                (setcdr lap1 (car (cdr tmp)))
-                (setq lap (delq lap0 lap))
-                (setq keep-going t))))
-        ;;
-        ;; X: varref-Y    ...     varset-Y goto-X  -->
-        ;; X: varref-Y Z: ... dup varset-Y goto-Z
-        ;; (varset-X goto-BACK, BACK: varref-X --> copy the varref down.)
-        ;; (This is so usual for while loops that it is worth handling).
-         ;;
-         ;; Here again, we could do it for stack-ref/stack-set, but
-        ;; that's replacing a stack-ref-Y with a stack-ref-0, which
-         ;; is a very minor improvement (if any), at the cost of
-        ;; more stack use and more byte-code.  Let's not do it.
-        ;;
-        ((and (eq (car lap1) 'byte-varset)
-              (eq (car lap2) 'byte-goto)
-              (not (memq (cdr lap2) rest)) ;Backwards jump
-              (eq (car (car (setq tmp (cdr (memq (cdr lap2) lap)))))
-                  'byte-varref)
-              (eq (cdr (car tmp)) (cdr lap1))
-              (not (memq (car (cdr lap1)) byte-boolean-vars)))
-         ;;(byte-compile-log-lap "  Pulled %s to end of loop" (car tmp))
-         (let ((newtag (byte-compile-make-tag)))
-           (byte-compile-log-lap
-            "  %s: %s ... %s %s\t-->\t%s: %s %s: ... %s %s %s"
-            (nth 1 (cdr lap2)) (car tmp)
-             lap1 lap2
-            (nth 1 (cdr lap2)) (car tmp)
-            (nth 1 newtag) 'byte-dup lap1
-            (cons 'byte-goto newtag)
-            )
-           (setcdr rest (cons (cons 'byte-dup 0) (cdr rest)))
-           (setcdr tmp (cons (setcdr lap2 newtag) (cdr tmp))))
-         (setq add-depth 1)
-         (setq keep-going t))
-        ;;
-        ;; goto-X Y: ... X: goto-if*-Y  -->  goto-if-not-*-X+1 Y:
-        ;; (This can pull the loop test to the end of the loop)
-        ;;
-        ((and (eq (car lap0) 'byte-goto)
-              (eq (car lap1) 'TAG)
-              (eq lap1
-                  (cdr (car (setq tmp (cdr (memq (cdr lap0) lap))))))
-              (memq (car (car tmp))
-                    '(byte-goto byte-goto-if-nil byte-goto-if-not-nil
-                      byte-goto-if-nil-else-pop)))
-         ;;           (byte-compile-log-lap "  %s %s, %s %s  --> moved 
conditional"
-         ;;                                 lap0 lap1 (cdr lap0) (car tmp))
-         (let ((newtag (byte-compile-make-tag)))
-           (byte-compile-log-lap
-            "%s %s: ... %s: %s\t-->\t%s ... %s:"
-            lap0 (nth 1 lap1) (nth 1 (cdr lap0)) (car tmp)
-            (cons (cdr (assq (car (car tmp))
-                             '((byte-goto-if-nil . byte-goto-if-not-nil)
-                               (byte-goto-if-not-nil . byte-goto-if-nil)
-                               (byte-goto-if-nil-else-pop .
-                                                          
byte-goto-if-not-nil-else-pop)
-                               (byte-goto-if-not-nil-else-pop .
-                                                              
byte-goto-if-nil-else-pop))))
-                  newtag)
-
-            (nth 1 newtag)
-            )
-           (setcdr tmp (cons (setcdr lap0 newtag) (cdr tmp)))
-           (if (eq (car (car tmp)) 'byte-goto-if-nil-else-pop)
-               ;; We can handle this case but not the -if-not-nil case,
-               ;; because we won't know which non-nil constant to push.
-               (setcdr rest (cons (cons 'byte-constant
-                                        (byte-compile-get-constant nil))
-                                  (cdr rest))))
-           (setcar lap0 (nth 1 (memq (car (car tmp))
-                                     '(byte-goto-if-nil-else-pop
-                                       byte-goto-if-not-nil
-                                       byte-goto-if-nil
-                                       byte-goto-if-not-nil
-                                       byte-goto byte-goto))))
-           )
-         (setq keep-going t))
-
-        ;;
-        ;; stack-set-M [discard/discardN ...]  -->  discardN-preserve-tos
-        ;; stack-set-M [discard/discardN ...]  -->  discardN
-        ;;
-        ((and (eq (car lap0) 'byte-stack-set)
-              (memq (car lap1) '(byte-discard byte-discardN))
-              (progn
-                ;; See if enough discard operations follow to expose or
-                ;; destroy the value stored by the stack-set.
-                (setq tmp (cdr rest))
-                (setq tmp2 (1- (cdr lap0)))
-                (setq tmp3 0)
-                (while (memq (car (car tmp)) '(byte-discard byte-discardN))
-                  (setq tmp3
-                         (+ tmp3 (if (eq (car (car tmp)) 'byte-discard)
-                                     1
-                                   (cdr (car tmp)))))
-                  (setq tmp (cdr tmp)))
-                (>= tmp3 tmp2)))
-         ;; Do the optimization.
-         (setq lap (delq lap0 lap))
-          (setcar lap1
-                  (if (= tmp2 tmp3)
-                      ;; The value stored is the new TOS, so pop one more
-                      ;; value (to get rid of the old value) using the
-                      ;; TOS-preserving discard operator.
-                      'byte-discardN-preserve-tos
-                    ;; Otherwise, the value stored is lost, so just use a
-                    ;; normal discard.
-                    'byte-discardN))
-          (setcdr lap1 (1+ tmp3))
-         (setcdr (cdr rest) tmp)
-         (byte-compile-log-lap "  %s [discard/discardN]...\t-->\t%s"
-                               lap0 lap1))
-
-        ;;
-        ;; discardN-preserve-tos return  -->  return
-        ;; dup return  -->  return
-        ;; stack-set-N return  -->  return     ; where N is TOS-1
-        ;;
-        ((and (eq (car lap1) 'byte-return)
-              (or (memq (car lap0) '(byte-discardN-preserve-tos byte-dup))
-                  (and (eq (car lap0) 'byte-stack-set)
-                       (= (cdr lap0) 1))))
-         (setq keep-going t)
-         ;; The byte-code interpreter will pop the stack for us, so
-         ;; we can just leave stuff on it.
-         (setq lap (delq lap0 lap))
-         (byte-compile-log-lap "  %s %s\t-->\t%s" lap0 lap1 lap1))
-
-        ;;
-        ;; goto-X ... X: discard  ==>  discard goto-Y ... X: discard Y:
-        ;;
-        ((and (eq (car lap0) 'byte-goto)
-              (setq tmp (cdr (memq (cdr lap0) lap)))
-              (memq (caar tmp) '(byte-discard byte-discardN
-                                 byte-discardN-preserve-tos)))
-         (byte-compile-log-lap
-          "  goto-X .. X: \t-->\t%s goto-X.. X: %s Y:"
-          (car tmp) (car tmp))
-         (setq keep-going t)
-         (let* ((newtag (byte-compile-make-tag))
-                ;; Make a copy, since we sometimes modify insts in-place!
-                (newdiscard (cons (caar tmp) (cdar tmp)))
-                (newjmp (cons (car lap0) newtag)))
-           (push newtag (cdr tmp))     ;Push new tag after the discard.
-           (setcar rest newdiscard)
-           (push newjmp (cdr rest))))
-
-        ;;
-        ;; const discardN-preserve-tos ==> discardN const
-        ;;
-        ((and (eq (car lap0) 'byte-constant)
-              (eq (car lap1) 'byte-discardN-preserve-tos))
-         (setq keep-going t)
-         (let ((newdiscard (cons 'byte-discardN (cdr lap1))))
-           (byte-compile-log-lap
-            "  %s %s\t-->\t%s %s" lap0 lap1 newdiscard lap0)
-           (setf (car rest) newdiscard)
-           (setf (cadr rest) lap0)))
-        )
-       (setq rest (cdr rest)))
-      )
+      (byte-compile-log-lap "  ---- %s pass"
+                            (if (eq keep-going 'first-time) "first" "next"))
+      (setq keep-going nil)
+      (let ((prev lap-head))
+        (while (cdr prev)
+          (let* ((rest (cdr prev))
+                (lap0 (car rest))
+                (lap1 (nth 1 rest))
+                (lap2 (nth 2 rest)))
+
+           ;; You may notice that sequences like "dup varset discard" are
+           ;; optimized but sequences like "dup varset TAG1: discard" are not.
+           ;; You may be tempted to change this; resist that temptation.
+
+            ;; Each clause in this `cond' statement must keep `prev' the
+            ;; predecessor of the remainder of the list for inspection.
+           (cond
+             ;;
+             ;; PUSH(K) discard(N) -->  <deleted> discard(N-K), N>K
+             ;; PUSH(K) discard(N) -->  <deleted>,              N=K
+             ;;  where PUSH(K) is a side-effect-free op such as
+             ;;  const, varref, dup
+             ;;
+             ((and (memq (car lap1) '(byte-discard byte-discardN))
+                  (memq (car lap0) side-effect-free))
+             (setq keep-going t)
+              (let* ((pushes (aref byte-stack+-info (symbol-value (car lap0))))
+                     (pops (if (eq (car lap1) 'byte-discardN) (cdr lap1) 1))
+                     (net-pops (- pops pushes)))
+                (cond ((= net-pops 0)
+                       (byte-compile-log-lap "  %s %s\t-->\t<deleted>"
+                                             lap0 lap1)
+                       (setcdr prev (cddr rest)))
+                      ((> net-pops 0)
+                       (byte-compile-log-lap
+                        "  %s %s\t-->\t<deleted> discard(%d)"
+                        lap0 lap1 net-pops)
+                       (setcar rest (if (eql net-pops 1)
+                                        (cons 'byte-discard nil)
+                                      (cons 'byte-discardN net-pops)))
+                       (setcdr rest (cddr rest)))
+                      (t (error "Optimizer error: too much on the stack")))))
+            ;;
+            ;; goto(X)              X:  -->          X:
+             ;; goto-if-[not-]nil(X) X:  -->  discard X:
+            ;;
+            ((and (memq (car lap0) byte-goto-ops)
+                  (eq (cdr lap0) lap1))
+             (cond ((eq (car lap0) 'byte-goto)
+                    (byte-compile-log-lap "  %s %s\t-->\t<deleted> %s"
+                                           lap0 lap1 lap1)
+                     (setcdr prev (cdr rest)))
+                   ((memq (car lap0) byte-goto-always-pop-ops)
+                    (byte-compile-log-lap "  %s %s\t-->\tdiscard %s"
+                                           lap0 lap1 lap1)
+                    (setcar lap0 'byte-discard)
+                    (setcdr lap0 0))
+                    ;; goto-*-else-pop(X) cannot occur here because it would
+                    ;; be a depth conflict.
+                   (t (error "Depth conflict at tag %d" (nth 2 lap0))))
+             (setq keep-going t))
+            ;;
+            ;; varset-X varref-X  -->  dup varset-X
+            ;; varbind-X varref-X  -->  dup varbind-X
+            ;; const/dup varset-X varref-X --> const/dup varset-X const/dup
+            ;; const/dup varbind-X varref-X --> const/dup varbind-X const/dup
+            ;; The latter two can enable other optimizations.
+            ;;
+             ;; For lexical variables, we could do the same
+             ;;   stack-set-X+1 stack-ref-X  -->  dup stack-set-X+2
+             ;; but this is a very minor gain, since dup is stack-ref-0,
+             ;; i.e. it's only better if X>5, and even then it comes
+             ;; at the cost of an extra stack slot.  Let's not bother.
+            ((and (eq 'byte-varref (car lap2))
+                   (eq (cdr lap1) (cdr lap2))
+                   (memq (car lap1) '(byte-varset byte-varbind))
+                   (let ((tmp (memq (car (cdr lap2)) byte-boolean-vars)))
+                     (and
+                      (not (and tmp (not (eq (car lap0) 'byte-constant))))
+                      (progn
+                       (setq keep-going t)
+                        (if (memq (car lap0) '(byte-constant byte-dup))
+                            (let ((tmp (if (or (not tmp)
+                                               (macroexp--const-symbol-p
+                                                (car (cdr lap0))))
+                                           (cdr lap0)
+                                         (byte-compile-get-constant t))))
+                             (byte-compile-log-lap "  %s %s %s\t-->\t%s %s %s"
+                                                   lap0 lap1 lap2 lap0 lap1
+                                                   (cons (car lap0) tmp))
+                             (setcar lap2 (car lap0))
+                             (setcdr lap2 tmp))
+                         (byte-compile-log-lap "  %s %s\t-->\tdup %s"
+                                                lap1 lap2 lap1)
+                         (setcar lap2 (car lap1))
+                         (setcar lap1 'byte-dup)
+                         (setcdr lap1 0)
+                         ;; The stack depth gets locally increased, so we will
+                         ;; increase maxdepth in case depth = maxdepth here.
+                         ;; This can cause the third argument to byte-code to
+                         ;; be larger than necessary.
+                         (setq add-depth 1))
+                        t)))))
+            ;;
+            ;; dup varset-X discard  -->  varset-X
+            ;; dup varbind-X discard  -->  varbind-X
+             ;; dup stack-set-X discard  -->  stack-set-X-1
+            ;; (the varbind variant can emerge from other optimizations)
+            ;;
+            ((and (eq 'byte-dup (car lap0))
+                  (eq 'byte-discard (car lap2))
+                  (memq (car lap1) '(byte-varset byte-varbind
+                                                  byte-stack-set)))
+             (setq keep-going t)
+              (setcdr prev (cdr rest))          ; remove dup
+              (setcdr (cdr rest) (cdddr rest))  ; remove discard
+              (cond ((not (eq (car lap1) 'byte-stack-set))
+                    (byte-compile-log-lap "  %s %s %s\t-->\t%s"
+                                           lap0 lap1 lap2 lap1))
+                    ((eql (cdr lap1) 1)
+                    (byte-compile-log-lap "  %s %s %s\t-->\t<deleted>"
+                                           lap0 lap1 lap2))
+                    (t
+                     (let ((n (1- (cdr lap1))))
+                      (byte-compile-log-lap "  %s %s %s\t-->\t%s"
+                                             lap0 lap1 lap2
+                                             (cons (car lap1) n))
+                       (setcdr lap1 n)))))
+            ;;
+            ;; not goto-X-if-nil              -->  goto-X-if-non-nil
+            ;; not goto-X-if-non-nil          -->  goto-X-if-nil
+            ;;
+            ;; it is wrong to do the same thing for the -else-pop variants.
+            ;;
+            ((and (eq 'byte-not (car lap0))
+                  (memq (car lap1) '(byte-goto-if-nil byte-goto-if-not-nil)))
+              (let ((not-goto (if (eq (car lap1) 'byte-goto-if-nil)
+                                 'byte-goto-if-not-nil
+                               'byte-goto-if-nil)))
+               (byte-compile-log-lap "  not %s\t-->\t%s"
+                                      lap1 (cons not-goto (cdr lap1)))
+               (setcar lap1 not-goto)
+                (setcdr prev (cdr rest))    ; delete not
+               (setq keep-going t)))
+            ;;
+            ;; goto-X-if-nil     goto-Y X:  -->  goto-Y-if-non-nil X:
+            ;; goto-X-if-non-nil goto-Y X:  -->  goto-Y-if-nil     X:
+            ;;
+            ;; it is wrong to do the same thing for the -else-pop variants.
+            ;;
+            ((and (memq (car lap0)
+                         '(byte-goto-if-nil byte-goto-if-not-nil)) ; gotoX
+                  (eq 'byte-goto (car lap1))                      ; gotoY
+                  (eq (cdr lap0) lap2))                           ; TAG X
+             (let ((inverse (if (eq 'byte-goto-if-nil (car lap0))
+                                'byte-goto-if-not-nil 'byte-goto-if-nil)))
+               (byte-compile-log-lap "  %s %s %s\t-->\t%s %s"
+                                     lap0 lap1 lap2
+                                     (cons inverse (cdr lap1)) lap2)
+                (setcdr prev (cdr rest))
+               (setcar lap1 inverse)
+               (setq keep-going t)))
+            ;;
+            ;; const goto-if-* --> whatever
+            ;;
+            ((and (eq 'byte-constant (car lap0))
+                  (memq (car lap1) byte-conditional-ops)
+                   ;; Must be an actual constant, not a closure variable.
+                   (consp (cdr lap0)))
+             (cond ((if (memq (car lap1) '(byte-goto-if-nil
+                                            byte-goto-if-nil-else-pop))
+                         (car (cdr lap0))
+                       (not (car (cdr lap0))))
+                     ;; Branch not taken.
+                    (byte-compile-log-lap "  %s %s\t-->\t<deleted>"
+                                          lap0 lap1)
+                     (setcdr prev (cddr rest))) ; delete both
+                   ((memq (car lap1) byte-goto-always-pop-ops)
+                     ;; Always-pop branch taken.
+                    (byte-compile-log-lap "  %s %s\t-->\t%s"
+                                          lap0 lap1
+                                          (cons 'byte-goto (cdr lap1)))
+                     (setcdr prev (cdr rest)) ; delete const
+                    (setcar lap1 'byte-goto))
+                    (t  ; -else-pop branch taken: keep const
+                    (byte-compile-log-lap "  %s %s\t-->\t%s %s"
+                                           lap0 lap1
+                                           lap0 (cons 'byte-goto (cdr lap1)))
+                    (setcar lap1 'byte-goto)))
+              (setq keep-going t))
+            ;;
+            ;; varref-X varref-X  -->  varref-X dup
+            ;; varref-X [dup ...] varref-X  -->  varref-X [dup ...] dup
+            ;; stackref-X [dup ...] stackref-X+N --> stackref-X [dup ...] dup
+            ;; We don't optimize the const-X variations on this here,
+            ;; because that would inhibit some goto optimizations; we
+            ;; optimize the const-X case after all other optimizations.
+            ;;
+            ((and (memq (car lap0) '(byte-varref byte-stack-ref))
+                   (let ((tmp (cdr rest))
+                         (tmp2 0))
+                    (while (eq (car (car tmp)) 'byte-dup)
+                      (setq tmp2 (1+ tmp2))
+                       (setq tmp (cdr tmp)))
+                    (and (eq (if (eq 'byte-stack-ref (car lap0))
+                                  (+ tmp2 1 (cdr lap0))
+                                (cdr lap0))
+                              (cdr (car tmp)))
+                         (eq (car lap0) (car (car tmp)))
+                          (progn
+                           (when (memq byte-optimize-log '(t byte))
+                             (let ((str "")
+                                   (tmp2 (cdr rest)))
+                               (while (not (eq tmp tmp2))
+                                 (setq tmp2 (cdr tmp2))
+                                  (setq str (concat str " dup")))
+                               (byte-compile-log-lap "  %s%s %s\t-->\t%s%s dup"
+                                                     lap0 str lap0 lap0 str)))
+                           (setq keep-going t)
+                           (setcar (car tmp) 'byte-dup)
+                           (setcdr (car tmp) 0)
+                            t)))))
+            ;;
+            ;; TAG1: TAG2: --> <deleted> TAG2:
+            ;; (and other references to TAG1 are replaced with TAG2)
+            ;;
+            ((and (eq (car lap0) 'TAG)
+                  (eq (car lap1) 'TAG))
+             (byte-compile-log-lap "  adjacent tags %d and %d merged"
+                                   (nth 1 lap1) (nth 1 lap0))
+              (let ((tmp3 (cdr lap-head)))
+               (while (let ((tmp2 (rassq lap0 tmp3)))
+                         (and tmp2
+                             (progn
+                                (setcdr tmp2 lap1)
+                               (setq tmp3 (cdr (memq tmp2 tmp3)))
+                                t))))
+                (setcdr prev (cdr rest))
+               (setq keep-going t)
+                ;; replace references to tag in jump tables, if any
+                (dolist (table byte-compile-jump-tables)
+                  (maphash #'(lambda (value tag)
+                               (when (equal tag lap0)
+                                 (puthash value lap1 table)))
+                           table))))
+            ;;
+            ;; unused-TAG: --> <deleted>
+            ;;
+            ((and (eq 'TAG (car lap0))
+                  (not (rassq lap0 (cdr lap-head)))
+                   ;; make sure this tag isn't used in a jump-table
+                   (cl-loop for table in byte-compile-jump-tables
+                            when (member lap0 (hash-table-values table))
+                            return nil finally return t))
+             (byte-compile-log-lap "  unused tag %d removed" (nth 1 lap0))
+              (setcdr prev (cdr rest))
+              (setq keep-going t))
+            ;;
+            ;; goto   ... --> goto   <delete until TAG or end>
+            ;; return ... --> return <delete until TAG or end>
+             ;;
+            ((and (memq (car lap0) '(byte-goto byte-return))
+                  (not (memq (car lap1) '(TAG nil))))
+             (let ((i 0)
+                    (tmp rest)
+                   (opt-p (memq byte-optimize-log '(t byte)))
+                   str deleted)
+               (while (and (setq tmp (cdr tmp))
+                           (not (eq 'TAG (car (car tmp)))))
+                 (if opt-p (setq deleted (cons (car tmp) deleted)
+                                 str (concat str " %s")
+                                 i (1+ i))))
+               (if opt-p
+                   (let ((tagstr
+                          (if (eq 'TAG (car (car tmp)))
+                              (format "%d:" (car (cdr (car tmp))))
+                            (or (car tmp) ""))))
+                     (if (< i 6)
+                         (apply 'byte-compile-log-lap-1
+                                (concat "  %s" str
+                                        " %s\t-->\t%s <deleted> %s")
+                                lap0
+                                (nconc (nreverse deleted)
+                                       (list tagstr lap0 tagstr)))
+                       (byte-compile-log-lap
+                        "  %s <%d unreachable op%s> %s\t-->\t%s <deleted> %s"
+                        lap0 i (if (= i 1) "" "s")
+                        tagstr lap0 tagstr))))
+               (setcdr rest tmp)
+               (setq keep-going t)))
+            ;;
+            ;; <safe-op> unbind --> unbind <safe-op>
+            ;; (this may enable other optimizations.)
+            ;;
+            ((and (eq 'byte-unbind (car lap1))
+                  (memq (car lap0) byte-after-unbind-ops))
+             (byte-compile-log-lap "  %s %s\t-->\t%s %s" lap0 lap1 lap1 lap0)
+             (setcar rest lap1)
+             (setcar (cdr rest) lap0)
+             (setq keep-going t))
+            ;;
+            ;; varbind-X unbind-N            -->  discard unbind-(N-1)
+            ;; save-excursion unbind-N       -->  unbind-(N-1)
+            ;; save-restriction unbind-N     -->  unbind-(N-1)
+            ;; save-current-buffer unbind-N  -->  unbind-(N-1)
+            ;;
+            ((and (eq 'byte-unbind (car lap1))
+                  (memq (car lap0) '(byte-varbind byte-save-excursion
+                                                  byte-save-restriction
+                                                   byte-save-current-buffer))
+                  (< 0 (cdr lap1)))
+              (setcdr lap1 (1- (cdr lap1)))
+             (when (zerop (cdr lap1))
+                (setcdr rest (cddr rest)))
+             (if (eq (car lap0) 'byte-varbind)
+                 (setcar rest (cons 'byte-discard 0))
+                (setcdr prev (cddr prev)))
+             (byte-compile-log-lap "  %s %s\t-->\t%s %s"
+                                   lap0 (cons (car lap1) (1+ (cdr lap1)))
+                                   (if (eq (car lap0) 'byte-varbind)
+                                       (car rest)
+                                     (car (cdr rest)))
+                                   (if (and (/= 0 (cdr lap1))
+                                            (eq (car lap0) 'byte-varbind))
+                                       (car (cdr rest))
+                                     ""))
+             (setq keep-going t))
+            ;;
+            ;; goto*-X ... X: goto-Y  --> goto*-Y
+            ;; goto-X ...  X: return  --> return
+            ;;
+            ((and (memq (car lap0) byte-goto-ops)
+                   (let ((tmp (nth 1 (memq (cdr lap0) (cdr lap-head)))))
+                     (and
+                     (memq (car tmp) '(byte-goto byte-return))
+                      (or (eq (car lap0) 'byte-goto)
+                         (eq (car tmp) 'byte-goto))
+                      (not (eq (cdr tmp) (cdr lap0)))
+                      (progn
+                       (byte-compile-log-lap "  %s [%s]\t-->\t%s"
+                                              (car lap0) tmp
+                                              (if (eq (car tmp) 'byte-return)
+                                                  tmp
+                                                (cons (car lap0) (cdr tmp))))
+                       (when (eq (car tmp) 'byte-return)
+                         (setcar lap0 'byte-return))
+                       (setcdr lap0 (cdr tmp))
+                       (setq keep-going t)
+                        t)))))
+
+             ;;
+             ;; OP goto(X) Y: OP X: -> Y: OP X:
+             ;;
+             ((and (eq (car lap1) 'byte-goto)
+                   (eq (car lap2) 'TAG)
+                   (let ((lap3 (nth 3 rest)))
+                     (and (eq (car lap0) (car lap3))
+                          (eq (cdr lap0) (cdr lap3))
+                          (eq (cdr lap1) (nth 4 rest)))))
+              (byte-compile-log-lap "  %s %s %s %s %s\t-->\t%s %s %s"
+                                    lap0 lap1 lap2
+                                    (nth 3 rest)  (nth 4 rest)
+                                    lap2 (nth 3 rest) (nth 4 rest))
+              (setcdr prev (cddr rest))
+              (setq keep-going t))
+
+             ;;
+             ;; OP const return  -->  const return
+             ;;  where OP is side-effect-free (or mere stack manipulation).
+             ;;
+             ((and (eq (car lap1) 'byte-constant)
+                   (eq (car (nth 2 rest)) 'byte-return)
+                   (or (memq (car lap0) '( byte-discard byte-discardN
+                                           byte-discardN-preserve-tos
+                                           byte-stack-set))
+                       (memq (car lap0) side-effect-free)))
+              (setq keep-going t)
+              (setq add-depth 1)
+              (setcdr prev (cdr rest))
+              (byte-compile-log-lap "  %s %s %s\t-->\t%s %s"
+                                    lap0 lap1 (nth 2 rest) lap1 (nth 2 rest)))
+
+            ;;
+            ;; goto-*-else-pop X ... X: goto-if-* --> whatever
+            ;; goto-*-else-pop X ... X: discard --> whatever
+            ;;
+            ((and (memq (car lap0) '(byte-goto-if-nil-else-pop
+                                     byte-goto-if-not-nil-else-pop))
+                   (let ((tmp (cdr (memq (cdr lap0) (cdr lap-head)))))
+                     (and
+                     (memq (caar tmp)
+                           (eval-when-compile
+                             (cons 'byte-discard byte-conditional-ops)))
+                     (not (eq lap0 (car tmp)))
+                      (let ((tmp2 (car tmp))
+                            (tmp3 (assq (car lap0)
+                                        '((byte-goto-if-nil-else-pop
+                                          byte-goto-if-nil)
+                                         (byte-goto-if-not-nil-else-pop
+                                          byte-goto-if-not-nil)))))
+                       (if (memq (car tmp2) tmp3)
+                           (progn (setcar lap0 (car tmp2))
+                                  (setcdr lap0 (cdr tmp2))
+                                  (byte-compile-log-lap
+                                    "  %s-else-pop [%s]\t-->\t%s"
+                                   (car lap0) tmp2 lap0))
+                         ;; Get rid of the -else-pop's and jump one
+                         ;; step further.
+                         (or (eq 'TAG (car (nth 1 tmp)))
+                             (setcdr tmp (cons (byte-compile-make-tag)
+                                               (cdr tmp))))
+                         (byte-compile-log-lap "  %s [%s]\t-->\t%s <skip>"
+                                               (car lap0) tmp2 (nth 1 tmp3))
+                         (setcar lap0 (nth 1 tmp3))
+                         (setcdr lap0 (nth 1 tmp)))
+                       (setq keep-going t)
+                        t)))))
+            ;;
+            ;; const goto-X ... X: goto-if-* --> whatever
+            ;; const goto-X ... X: discard   --> whatever
+            ;;
+            ((and (eq (car lap0) 'byte-constant)
+                  (eq (car lap1) 'byte-goto)
+                   (let ((tmp (cdr (memq (cdr lap1) (cdr lap-head)))))
+                     (and
+                     (memq (caar tmp)
+                           (eval-when-compile
+                             (cons 'byte-discard byte-conditional-ops)))
+                     (not (eq lap1 (car tmp)))
+                     (let ((tmp2 (car tmp)))
+                       (cond ((and (consp (cdr lap0))
+                                   (memq (car tmp2)
+                                         (if (null (car (cdr lap0)))
+                                             '(byte-goto-if-nil
+                                                byte-goto-if-nil-else-pop)
+                                           '(byte-goto-if-not-nil
+                                             byte-goto-if-not-nil-else-pop))))
+                              (byte-compile-log-lap
+                                "  %s goto [%s]\t-->\t%s %s"
+                                lap0 tmp2 lap0 tmp2)
+                              (setcar lap1 (car tmp2))
+                              (setcdr lap1 (cdr tmp2))
+                              ;; Let next step fix the (const,goto-if*) seq.
+                              (setq keep-going t))
+                             ((or (consp (cdr lap0))
+                                  (eq (car tmp2) 'byte-discard))
+                              ;; Jump one step further
+                              (byte-compile-log-lap
+                               "  %s goto [%s]\t-->\t<deleted> goto <skip>"
+                               lap0 tmp2)
+                              (or (eq 'TAG (car (nth 1 tmp)))
+                                  (setcdr tmp (cons (byte-compile-make-tag)
+                                                    (cdr tmp))))
+                              (setcdr lap1 (car (cdr tmp)))
+                               (setcdr prev (cdr rest))
+                              (setq keep-going t))
+                              (t
+                               (setq prev (cdr prev))))
+                        t)))))
+            ;;
+            ;; X: varref-Y    ...     varset-Y goto-X  -->
+            ;; X: varref-Y Z: ... dup varset-Y goto-Z
+            ;; (varset-X goto-BACK, BACK: varref-X --> copy the varref down.)
+            ;; (This is so usual for while loops that it is worth handling).
+             ;;
+             ;; Here again, we could do it for stack-ref/stack-set, but
+            ;; that's replacing a stack-ref-Y with a stack-ref-0, which
+             ;; is a very minor improvement (if any), at the cost of
+            ;; more stack use and more byte-code.  Let's not do it.
+            ;;
+            ((and (eq (car lap1) 'byte-varset)
+                  (eq (car lap2) 'byte-goto)
+                  (not (memq (cdr lap2) rest)) ;Backwards jump
+                   (let ((tmp (cdr (memq (cdr lap2) (cdr lap-head)))))
+                     (and
+                     (eq (car (car tmp)) 'byte-varref)
+                     (eq (cdr (car tmp)) (cdr lap1))
+                     (not (memq (car (cdr lap1)) byte-boolean-vars))
+                     (let ((newtag (byte-compile-make-tag)))
+                       (byte-compile-log-lap
+                        "  %s: %s ... %s %s\t-->\t%s: %s %s: ... %s %s %s"
+                        (nth 1 (cdr lap2)) (car tmp)
+                         lap1 lap2
+                        (nth 1 (cdr lap2)) (car tmp)
+                        (nth 1 newtag) 'byte-dup lap1
+                        (cons 'byte-goto newtag)
+                        )
+                       (setcdr rest (cons (cons 'byte-dup 0) (cdr rest)))
+                       (setcdr tmp (cons (setcdr lap2 newtag) (cdr tmp)))
+                       (setq add-depth 1)
+                       (setq keep-going t)
+                        t)))))
+            ;;
+            ;; goto-X Y: ... X: goto-if*-Y  -->  goto-if-not-*-X+1 Y:
+            ;; (This can pull the loop test to the end of the loop)
+            ;;
+            ((and (eq (car lap0) 'byte-goto)
+                  (eq (car lap1) 'TAG)
+                   (let ((tmp (cdr (memq (cdr lap0) (cdr lap-head)))))
+                     (and
+                     (eq lap1 (cdar tmp))
+                     (memq (car (car tmp))
+                           '( byte-goto byte-goto-if-nil byte-goto-if-not-nil
+                              byte-goto-if-nil-else-pop))
+                     (let ((newtag (byte-compile-make-tag)))
+                       (byte-compile-log-lap
+                        "  %s %s ... %s %s\t-->\t%s ... %s"
+                        lap0 lap1 (cdr lap0) (car tmp)
+                        (cons (cdr (assq (car (car tmp))
+                                         '((byte-goto-if-nil
+                                             . byte-goto-if-not-nil)
+                                           (byte-goto-if-not-nil
+                                             . byte-goto-if-nil)
+                                           (byte-goto-if-nil-else-pop
+                                             . byte-goto-if-not-nil-else-pop)
+                                           (byte-goto-if-not-nil-else-pop
+                                             . byte-goto-if-nil-else-pop))))
+                              newtag)
+                        newtag)
+                       (setcdr tmp (cons (setcdr lap0 newtag) (cdr tmp)))
+                       (when (eq (car (car tmp)) 'byte-goto-if-nil-else-pop)
+                         ;; We can handle this case but not the
+                         ;; -if-not-nil case, because we won't know
+                         ;; which non-nil constant to push.
+                         (setcdr rest
+                                  (cons (cons 'byte-constant
+                                             (byte-compile-get-constant nil))
+                                       (cdr rest))))
+                       (setcar lap0 (nth 1 (memq (car (car tmp))
+                                                 '(byte-goto-if-nil-else-pop
+                                                   byte-goto-if-not-nil
+                                                   byte-goto-if-nil
+                                                   byte-goto-if-not-nil
+                                                   byte-goto byte-goto))))
+                       (setq keep-going t)
+                        t)))))
+
+             ;;
+             ;; discardN-preserve-tos(X) discardN-preserve-tos(Y)
+             ;; --> discardN-preserve-tos(X+Y)
+             ;;  where stack-set(1) is accepted as discardN-preserve-tos(1)
+             ;;
+             ((and (or (eq (car lap0) 'byte-discardN-preserve-tos)
+                       (and (eq (car lap0) 'byte-stack-set)
+                            (eql (cdr lap0) 1)))
+                   (or (eq (car lap1) 'byte-discardN-preserve-tos)
+                       (and (eq (car lap1) 'byte-stack-set)
+                            (eql (cdr lap1) 1))))
+              (setq keep-going t)
+              (let ((new-op (cons 'byte-discardN-preserve-tos
+                                  ;; This happens to work even when either
+                                  ;; op is stack-set(1).
+                                  (+ (cdr lap0) (cdr lap1)))))
+                (byte-compile-log-lap "  %s %s\t-->\t%s" lap0 lap1 new-op)
+                (setcar rest new-op)
+                (setcdr rest (cddr rest))))
+
+            ;;
+            ;; stack-set-M [discard/discardN ...]  -->  discardN-preserve-tos
+            ;; stack-set-M [discard/discardN ...]  -->  discardN
+            ;;
+            ((and (eq (car lap0) 'byte-stack-set)
+                  (memq (car lap1) '(byte-discard byte-discardN))
+                   (let ((tmp2 (1- (cdr lap0)))
+                         (tmp3 0)
+                         (tmp (cdr rest)))
+                    ;; See if enough discard operations follow to expose or
+                    ;; destroy the value stored by the stack-set.
+                    (while (memq (car (car tmp)) '(byte-discard byte-discardN))
+                      (setq tmp3
+                             (+ tmp3 (if (eq (car (car tmp)) 'byte-discard)
+                                         1
+                                       (cdr (car tmp)))))
+                      (setq tmp (cdr tmp)))
+                     (and
+                     (>= tmp3 tmp2)
+                      (progn
+                       ;; Do the optimization.
+                        (setcdr prev (cdr rest))
+                        (setcar lap1
+                                (if (= tmp2 tmp3)
+                                    ;; The value stored is the new TOS, so pop
+                                    ;; one more value (to get rid of the old
+                                    ;; value) using TOS-preserving discard.
+                                    'byte-discardN-preserve-tos
+                                  ;; Otherwise, the value stored is lost,
+                                  ;; so just use a normal discard.
+                                  'byte-discardN))
+                        (setcdr lap1 (1+ tmp3))
+                       (setcdr (cdr rest) tmp)
+                       (byte-compile-log-lap
+                         "  %s [discard/discardN]...\t-->\t%s" lap0 lap1)
+                        (setq keep-going t)
+                        t
+                        )))))
+
+            ;;
+            ;; discardN-preserve-tos return  -->  return
+            ;; dup return  -->  return
+            ;; stack-set(1) return  -->  return
+            ;;
+            ((and (eq (car lap1) 'byte-return)
+                  (or (memq (car lap0) '(byte-discardN-preserve-tos byte-dup))
+                      (and (eq (car lap0) 'byte-stack-set)
+                           (= (cdr lap0) 1))))
+             (setq keep-going t)
+             ;; The byte-code interpreter will pop the stack for us, so
+             ;; we can just leave stuff on it.
+             (setcdr prev (cdr rest))
+             (byte-compile-log-lap "  %s %s\t-->\t%s" lap0 lap1 lap1))
+
+            ;;
+            ;; goto-X ... X: discard  ==>  discard goto-Y ... X: discard Y:
+            ;;
+            ((and (eq (car lap0) 'byte-goto)
+                   (let ((tmp (cdr (memq (cdr lap0) (cdr lap-head)))))
+                     (and
+                      tmp
+                      (or (memq (caar tmp) '(byte-discard byte-discardN))
+                          ;; Make sure we don't hoist a discardN-preserve-tos
+                          ;; that really should be merged or deleted instead.
+                          (and (eq (caar tmp) 'byte-discardN-preserve-tos)
+                               (let ((next (cadr tmp)))
+                                 (not (or (memq (car next)
+                                                '(byte-discardN-preserve-tos
+                                                  byte-return))
+                                          (and (eq (car next) 'byte-stack-set)
+                                               (eql (cdr next) 1)))))))
+                      (progn
+                       (byte-compile-log-lap
+                        "  goto-X .. X: \t-->\t%s goto-X.. X: %s Y:"
+                        (car tmp) (car tmp))
+                       (setq keep-going t)
+                       (let* ((newtag (byte-compile-make-tag))
+                              ;; Make a copy, since we sometimes modify
+                              ;; insts in-place!
+                              (newdiscard (cons (caar tmp) (cdar tmp)))
+                              (newjmp (cons (car lap0) newtag)))
+                          ;; Push new tag after the discard.
+                         (push newtag (cdr tmp))
+                         (setcar rest newdiscard)
+                         (push newjmp (cdr rest)))
+                        t)))))
+
+            ;;
+            ;; const discardN-preserve-tos ==> discardN const
+             ;; const stack-set(1)          ==> discard const
+            ;;
+            ((and (eq (car lap0) 'byte-constant)
+                  (or (eq (car lap1) 'byte-discardN-preserve-tos)
+                       (and (eq (car lap1) 'byte-stack-set)
+                            (eql (cdr lap1) 1))))
+             (setq keep-going t)
+              (let ((newdiscard (if (eql (cdr lap1) 1)
+                                    (cons 'byte-discard nil)
+                                  (cons 'byte-discardN (cdr lap1)))))
+               (byte-compile-log-lap
+                "  %s %s\t-->\t%s %s" lap0 lap1 newdiscard lap0)
+               (setf (car rest) newdiscard)
+               (setf (cadr rest) lap0)))
+             (t
+              ;; If no rule matched, advance and try again.
+              (setq prev (cdr prev))))))))
     ;; Cleanup stage:
     ;; Rebuild byte-compile-constants / byte-compile-variables.
     ;; Simple optimizations that would inhibit other optimizations if they
@@ -2540,90 +2699,84 @@ If FOR-EFFECT is non-nil, the return value is assumed 
to be of no importance."
     ;; need to do more than once.
     (setq byte-compile-constants nil
          byte-compile-variables nil)
-    (setq rest lap)
     (byte-compile-log-lap "  ---- final pass")
-    (while rest
-      (setq lap0 (car rest)
-           lap1 (nth 1 rest))
-      (if (memq (car lap0) byte-constref-ops)
-         (if (memq (car lap0) '(byte-constant byte-constant2))
-             (unless (memq (cdr lap0) byte-compile-constants)
-               (setq byte-compile-constants (cons (cdr lap0)
-                                                  byte-compile-constants)))
-           (unless (memq (cdr lap0) byte-compile-variables)
-             (setq byte-compile-variables (cons (cdr lap0)
-                                                byte-compile-variables)))))
-      (cond (;;
-            ;; const-C varset-X const-C  -->  const-C dup varset-X
-            ;; const-C varbind-X const-C  -->  const-C dup varbind-X
-            ;;
-            (and (eq (car lap0) 'byte-constant)
-                 (eq (car (nth 2 rest)) 'byte-constant)
-                 (eq (cdr lap0) (cdr (nth 2 rest)))
-                 (memq (car lap1) '(byte-varbind byte-varset)))
-            (byte-compile-log-lap "  %s %s %s\t-->\t%s dup %s"
-                                  lap0 lap1 lap0 lap0 lap1)
-            (setcar (cdr (cdr rest)) (cons (car lap1) (cdr lap1)))
-            (setcar (cdr rest) (cons 'byte-dup 0))
-            (setq add-depth 1))
-           ;;
-           ;; const-X  [dup/const-X ...]   -->  const-X  [dup ...] dup
-           ;; varref-X [dup/varref-X ...]  -->  varref-X [dup ...] dup
-           ;;
-           ((memq (car lap0) '(byte-constant byte-varref))
-            (setq tmp rest
-                  tmp2 nil)
-            (while (progn
-                     (while (eq 'byte-dup (car (car (setq tmp (cdr tmp))))))
-                     (and (eq (cdr lap0) (cdr (car tmp)))
-                          (eq (car lap0) (car (car tmp)))))
-              (setcar tmp (cons 'byte-dup 0))
-              (setq tmp2 t))
-            (if tmp2
-                (byte-compile-log-lap
-                 "  %s [dup/%s]...\t-->\t%s dup..." lap0 lap0 lap0)))
-           ;;
-           ;; unbind-N unbind-M  -->  unbind-(N+M)
-           ;;
-           ((and (eq 'byte-unbind (car lap0))
-                 (eq 'byte-unbind (car lap1)))
-            (byte-compile-log-lap "  %s %s\t-->\t%s" lap0 lap1
-                                  (cons 'byte-unbind
-                                        (+ (cdr lap0) (cdr lap1))))
-            (setq lap (delq lap0 lap))
-            (setcdr lap1 (+ (cdr lap1) (cdr lap0))))
-
-           ;;
-           ;; discard/discardN/discardN-preserve-tos-X discard/discardN-Y  -->
-           ;; discardN-(X+Y)
-           ;;
-           ((and (memq (car lap0)
-                       '(byte-discard byte-discardN
-                         byte-discardN-preserve-tos))
-                 (memq (car lap1) '(byte-discard byte-discardN)))
-            (setq lap (delq lap0 lap))
-            (byte-compile-log-lap
-             "  %s %s\t-->\t(discardN %s)"
-             lap0 lap1
-             (+ (if (eq (car lap0) 'byte-discard) 1 (cdr lap0))
-                (if (eq (car lap1) 'byte-discard) 1 (cdr lap1))))
-            (setcdr lap1 (+ (if (eq (car lap0) 'byte-discard) 1 (cdr lap0))
-                            (if (eq (car lap1) 'byte-discard) 1 (cdr lap1))))
-            (setcar lap1 'byte-discardN))
-
-           ;;
-           ;; discardN-preserve-tos-X discardN-preserve-tos-Y  -->
-           ;; discardN-preserve-tos-(X+Y)
-           ;;
-           ((and (eq (car lap0) 'byte-discardN-preserve-tos)
-                 (eq (car lap1) 'byte-discardN-preserve-tos))
-            (setq lap (delq lap0 lap))
-            (setcdr lap1 (+ (cdr lap0) (cdr lap1)))
-            (byte-compile-log-lap "  %s %s\t-->\t%s" lap0 lap1 (car rest)))
-            )
-      (setq rest (cdr rest)))
-    (setq byte-compile-maxdepth (+ byte-compile-maxdepth add-depth)))
-  lap)
+    (let ((prev lap-head))
+      (while (cdr prev)
+        (let* ((rest (cdr prev))
+               (lap0 (car rest))
+              (lap1 (nth 1 rest)))
+          ;; FIXME: Would there ever be a `byte-constant2' op here?
+          (if (memq (car lap0) byte-constref-ops)
+             (if (memq (car lap0) '(byte-constant byte-constant2))
+                 (unless (memq (cdr lap0) byte-compile-constants)
+                   (setq byte-compile-constants (cons (cdr lap0)
+                                                      byte-compile-constants)))
+               (unless (memq (cdr lap0) byte-compile-variables)
+                 (setq byte-compile-variables (cons (cdr lap0)
+                                                    byte-compile-variables)))))
+          (cond
+           ;;
+          ;; const-C varset-X const-C  -->  const-C dup varset-X
+          ;; const-C varbind-X const-C  -->  const-C dup varbind-X
+          ;;
+          ((and (eq (car lap0) 'byte-constant)
+                (eq (car (nth 2 rest)) 'byte-constant)
+                (eq (cdr lap0) (cdr (nth 2 rest)))
+                (memq (car lap1) '(byte-varbind byte-varset)))
+           (byte-compile-log-lap "  %s %s %s\t-->\t%s dup %s"
+                                 lap0 lap1 lap0 lap0 lap1)
+           (setcar (cdr (cdr rest)) (cons (car lap1) (cdr lap1)))
+           (setcar (cdr rest) (cons 'byte-dup 0))
+           (setq add-depth 1))
+          ;;
+          ;; const-X  [dup/const-X ...]   -->  const-X  [dup ...] dup
+          ;; varref-X [dup/varref-X ...]  -->  varref-X [dup ...] dup
+          ;;
+          ((memq (car lap0) '(byte-constant byte-varref))
+           (let ((tmp rest)
+                 (tmp2 nil))
+             (while (progn
+                      (while (eq 'byte-dup (car (car (setq tmp (cdr tmp))))))
+                      (and (eq (cdr lap0) (cdr (car tmp)))
+                           (eq (car lap0) (car (car tmp)))))
+               (setcar tmp (cons 'byte-dup 0))
+               (setq tmp2 t))
+             (if tmp2
+                 (byte-compile-log-lap
+                  "  %s [dup/%s]...\t-->\t%s dup..." lap0 lap0 lap0)
+                (setq prev (cdr prev)))))
+          ;;
+          ;; unbind-N unbind-M  -->  unbind-(N+M)
+          ;;
+          ((and (eq 'byte-unbind (car lap0))
+                (eq 'byte-unbind (car lap1)))
+           (byte-compile-log-lap "  %s %s\t-->\t%s" lap0 lap1
+                                 (cons 'byte-unbind
+                                       (+ (cdr lap0) (cdr lap1))))
+           (setcdr prev (cdr rest))
+           (setcdr lap1 (+ (cdr lap1) (cdr lap0))))
+
+          ;;
+          ;; discard/discardN/discardN-preserve-tos-X discard/discardN-Y  -->
+          ;; discardN-(X+Y)
+          ;;
+          ((and (memq (car lap0)
+                      '(byte-discard byte-discardN
+                                     byte-discardN-preserve-tos))
+                (memq (car lap1) '(byte-discard byte-discardN)))
+           (setcdr prev (cdr rest))
+           (byte-compile-log-lap
+            "  %s %s\t-->\t(discardN %s)"
+            lap0 lap1
+            (+ (if (eq (car lap0) 'byte-discard) 1 (cdr lap0))
+               (if (eq (car lap1) 'byte-discard) 1 (cdr lap1))))
+           (setcdr lap1 (+ (if (eq (car lap0) 'byte-discard) 1 (cdr lap0))
+                           (if (eq (car lap1) 'byte-discard) 1 (cdr lap1))))
+           (setcar lap1 'byte-discardN))
+           (t
+            (setq prev (cdr prev)))))))
+    (setq byte-compile-maxdepth (+ byte-compile-maxdepth add-depth))
+    (cdr lap-head)))
 
 (provide 'byte-opt)
 
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index aa9521e5a65..e8a8fe37756 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -3748,7 +3748,7 @@ If it is nil, then the handler is 
\"byte-compile-SYMBOL.\""
                                      '((0 . byte-compile-no-args)
                                        (1 . byte-compile-one-arg)
                                        (2 . byte-compile-two-args)
-                                       (2-and . byte-compile-and-folded)
+                                        (2-cmp . byte-compile-cmp)
                                        (3 . byte-compile-three-args)
                                        (0-1 . byte-compile-zero-or-one-arg)
                                        (1-2 . byte-compile-one-or-two-args)
@@ -3827,11 +3827,11 @@ If it is nil, then the handler is 
\"byte-compile-SYMBOL.\""
 (byte-defop-compiler cons              2)
 (byte-defop-compiler aref              2)
 (byte-defop-compiler set               2)
-(byte-defop-compiler (= byte-eqlsign)  2-and)
-(byte-defop-compiler (< byte-lss)      2-and)
-(byte-defop-compiler (> byte-gtr)      2-and)
-(byte-defop-compiler (<= byte-leq)     2-and)
-(byte-defop-compiler (>= byte-geq)     2-and)
+(byte-defop-compiler (= byte-eqlsign)  2-cmp)
+(byte-defop-compiler (< byte-lss)      2-cmp)
+(byte-defop-compiler (> byte-gtr)      2-cmp)
+(byte-defop-compiler (<= byte-leq)     2-cmp)
+(byte-defop-compiler (>= byte-geq)     2-cmp)
 (byte-defop-compiler get               2)
 (byte-defop-compiler nth               2)
 (byte-defop-compiler substring         1-3)
@@ -3895,18 +3895,20 @@ If it is nil, then the handler is 
\"byte-compile-SYMBOL.\""
     (byte-compile-form (nth 2 form))
     (byte-compile-out (get (car form) 'byte-opcode) 0)))
 
-(defun byte-compile-and-folded (form)
-  "Compile calls to functions like `<='.
-These implicitly `and' together a bunch of two-arg bytecodes."
-  (let ((l (length form)))
-    (cond
-     ((< l 3) (byte-compile-form `(progn ,(nth 1 form) t)))
-     ((= l 3) (byte-compile-two-args form))
-     ;; Don't use `cl-every' here (see comment where we require cl-lib).
-     ((not (memq nil (mapcar #'macroexp-copyable-p (nthcdr 2 form))))
-      (byte-compile-form `(and (,(car form) ,(nth 1 form) ,(nth 2 form))
-                              (,(car form) ,@(nthcdr 2 form)))))
-     (t (byte-compile-normal-call form)))))
+(defun byte-compile-cmp (form)
+  "Compile calls to numeric comparisons such as `<', `=' etc."
+  ;; Lisp-level transforms should already have reduced valid calls to 2 args.
+  (if (not (= (length form) 3))
+      (byte-compile-subr-wrong-args form "1 or more")
+    (byte-compile-two-args
+     (if (macroexp-const-p (nth 1 form))
+         ;; First argument is constant: flip it so that the constant
+         ;; is last, which may allow more lapcode optimisations.
+         (let* ((op (car form))
+                (flipped-op (cdr (assq op '((< . >) (<= . >=)
+                                            (> . <) (>= . <=) (= . =))))))
+           (list flipped-op (nth 2 form) (nth 1 form)))
+       form))))
 
 (defun byte-compile-three-args (form)
   (if (not (= (length form) 4))
@@ -4061,9 +4063,15 @@ This function is never called when `lexical-binding' is 
nil."
      (byte-compile-constant 1)
      (byte-compile-out (get '* 'byte-opcode) 0))
     (3
-     (byte-compile-form (nth 1 form))
-     (byte-compile-form (nth 2 form))
-     (byte-compile-out (get (car form) 'byte-opcode) 0))
+     (let ((arg1 (nth 1 form))
+           (arg2 (nth 2 form)))
+       (when (and (memq (car form) '(+ *))
+                  (macroexp-const-p arg1))
+         ;; Put constant argument last for better LAP optimisation.
+         (cl-rotatef arg1 arg2))
+       (byte-compile-form arg1)
+       (byte-compile-form arg2)
+       (byte-compile-out (get (car form) 'byte-opcode) 0)))
     (_
      ;; >2 args: compile as a single function call.
      (byte-compile-normal-call form))))
diff --git a/lisp/emacs-lisp/cconv.el b/lisp/emacs-lisp/cconv.el
index e715bd90a00..e8d639903c1 100644
--- a/lisp/emacs-lisp/cconv.el
+++ b/lisp/emacs-lisp/cconv.el
@@ -483,10 +483,13 @@ places where they originally did not directly appear."
             (bf (if (stringp (car body)) (cdr body) body))
             (if (when (eq 'interactive (car-safe (car bf)))
                   (gethash form cconv--interactive-form-funs)))
+            (wrapped (pcase if (`#'(lambda (_cconv--dummy) .,_) t) (_ nil)))
             (cif (when if (cconv-convert if env extend)))
             (_ (pcase cif
-                 (`#'(lambda () ,form) (setf (cadr (car bf)) form) (setq cif 
nil))
                  ('nil nil)
+                 (`#',f
+                  (setf (cadr (car bf)) (if wrapped (nth 2 f) cif))
+                  (setq cif nil))
                  ;; The interactive form needs special treatment, so the form
                  ;; inside the `interactive' won't be used any further.
                  (_ (setf (cadr (car bf)) nil))))
@@ -494,7 +497,8 @@ places where they originally did not directly appear."
        (if (not cif)
            ;; Normal case, the interactive form needs no special treatment.
            cf
-         `(cconv--interactive-helper ,cf ,cif))))
+         `(cconv--interactive-helper
+           ,cf ,(if wrapped cif `(list 'quote ,cif))))))
 
     (`(internal-make-closure . ,_)
      (byte-compile-report-error
@@ -742,7 +746,8 @@ This function does not return anything but instead fills the
        (when (eq 'interactive (car-safe (car bf)))
          (let ((if (cadr (car bf))))
            (unless (macroexp-const-p if) ;Optimize this common case.
-             (let ((f `#'(lambda () ,if)))
+             (let ((f (if (eq 'function (car-safe if)) if
+                        `#'(lambda (_cconv--dummy) ,if))))
                (setf (gethash form cconv--interactive-form-funs) f)
                (cconv-analyze-form f env))))))
      (cconv--analyze-function vrs body-forms env form))
diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el
index 1fe7a303344..1beff421038 100644
--- a/lisp/emacs-lisp/comp.el
+++ b/lisp/emacs-lisp/comp.el
@@ -4136,13 +4136,16 @@ the deferred compilation mechanism."
                 (native-elisp-load data)))
           ;; We may have created a temporary file when we're being
           ;; called with something other than a file as the argument.
-          ;; Delete it.
+          ;; Delete it if we can.
           (when (and (not (stringp function-or-file))
                      (not output)
                      comp-ctxt
                      (comp-ctxt-output comp-ctxt)
                      (file-exists-p (comp-ctxt-output comp-ctxt)))
-            (delete-file (comp-ctxt-output comp-ctxt))))))))
+            (cond ((eq 'windows-nt system-type)
+                   ;; We may still be using the temporary .eln file.
+                   (ignore-errors (delete-file (comp-ctxt-output comp-ctxt))))
+                  (t (delete-file (comp-ctxt-output comp-ctxt))))))))))
 
 (defun native-compile-async-skip-p (file load selector)
   "Return non-nil if FILE's compilation should be skipped.
diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el
index bacc105a214..367f59e8785 100644
--- a/lisp/emacs-lisp/lisp-mode.el
+++ b/lisp/emacs-lisp/lisp-mode.el
@@ -182,6 +182,7 @@ to a package-local <package>-loaddefs.el file.")
 ;; CL
 (put 'defconstant 'doc-string-elt 3)
 (put 'defparameter 'doc-string-elt 3)
+(put 'defstruct 'doc-string-elt 2)
 
 (defvar lisp-doc-string-elt-property 'doc-string-elt
   "The symbol property that holds the docstring position info.")
diff --git a/lisp/emacs-lisp/nadvice.el b/lisp/emacs-lisp/nadvice.el
index 85934d9ed0a..e457387acc9 100644
--- a/lisp/emacs-lisp/nadvice.el
+++ b/lisp/emacs-lisp/nadvice.el
@@ -178,20 +178,38 @@ DOC is a string where \"FUNCTION\" and \"OLDFUN\" are 
expected.")
    ;; ((functionp spec) (funcall spec))
    (t (eval spec))))
 
+(defun advice--interactive-form-1 (function)
+  "Like `interactive-form' but preserves the static context if needed."
+  (let ((if (interactive-form function)))
+    (if (or (null if) (not (eq 'closure (car-safe function))))
+        if
+      (cl-assert (eq 'interactive (car if)))
+      (let ((form (cadr if)))
+        (if (macroexp-const-p form)
+            if
+          ;; The interactive is expected to be run in the static context
+          ;; that the function captured.
+          (let ((ctx (nth 1 function)))
+            `(interactive
+              ,(let* ((f (if (eq 'function (car-safe form)) (cadr form) form)))
+                 ;; If the form jut returns a function, preserve the fact that
+                 ;; it just returns a function, which is an info we use in
+                 ;; `advice--make-interactive-form'.
+                 (if (eq 'lambda (car-safe f))
+                     `',(eval form ctx)
+                   `(eval ',form ',ctx))))))))))
+
 (defun advice--interactive-form (function)
   "Like `interactive-form' but tries to avoid autoloading functions."
   (if (not (and (symbolp function) (autoloadp (indirect-function function))))
-      (interactive-form function)
+      (advice--interactive-form-1 function)
     (when (commandp function)
       `(interactive (advice-eval-interactive-spec
-                     (cadr (interactive-form ',function)))))))
+                     (cadr (advice--interactive-form-1 ',function)))))))
 
 (defun advice--make-interactive-form (iff ifm)
-  ;; TODO: make it so that interactive spec can be a constant which
-  ;; dynamically checks the advice--car/cdr to do its job.
-  ;; For that, advice-eval-interactive-spec needs to be more faithful.
   (let* ((fspec (cadr iff)))
-    (when (eq 'function (car-safe fspec)) ;; Macroexpanded lambda?
+    (when (memq (car-safe fspec) '(function quote)) ;; Macroexpanded lambda?
       (setq fspec (eval fspec t)))
     (if (functionp fspec)
         `(funcall ',fspec ',(cadr ifm))
diff --git a/lisp/emacs-lisp/oclosure.el b/lisp/emacs-lisp/oclosure.el
index f5a150ac4ae..40f1f54eed0 100644
--- a/lisp/emacs-lisp/oclosure.el
+++ b/lisp/emacs-lisp/oclosure.el
@@ -568,7 +568,7 @@ This has 2 uses:
 (defun cconv--interactive-helper (fun if)
   "Add interactive \"form\" IF to FUN.
 Returns a new command that otherwise behaves like FUN.
-IF should actually not be a form but a function of no arguments."
+IF can be an ELisp form to be interpreted or a function of no arguments."
   (oclosure-lambda (cconv--interactive-helper (fun fun) (if if))
       (&rest args)
     (apply (if (called-interactively-p 'any)
diff --git a/lisp/emacs-lisp/range.el b/lisp/emacs-lisp/range.el
index 1165fcbbd7d..f441c240a27 100644
--- a/lisp/emacs-lisp/range.el
+++ b/lisp/emacs-lisp/range.el
@@ -194,7 +194,7 @@ these ranges."
       (nreverse result)))))
 
 (defun range-add-list (ranges list)
-  "Return a list of ranges that has all articles from both RANGES and LIST.
+  "Return a list of ranges that has all numbers from both RANGES and LIST.
 Note: LIST has to be sorted over `<'."
   (if (not ranges)
       (range-compress-list list)
@@ -249,9 +249,9 @@ Note: LIST has to be sorted over `<'."
       out)))
 
 (defun range-remove (range1 range2)
-  "Return a range that has all articles from RANGE2 removed from RANGE1.
+  "Return a range that has all numbers from RANGE2 removed from RANGE1.
 The returned range is always a list.  RANGE2 can also be a unsorted
-list of articles.  RANGE1 is modified by side effects, RANGE2 is not
+list of numbers.  RANGE1 is modified by side effects, RANGE2 is not
 modified."
   (if (or (null range1) (null range2))
       range1
@@ -345,7 +345,7 @@ modified."
 
 (defun range-list-intersection (list ranges)
   "Return a list of numbers in LIST that are members of RANGES.
-oLIST is a sorted list."
+LIST is a sorted list."
   (setq ranges (range-normalize ranges))
   (let (number result)
     (while (setq number (pop list))
diff --git a/lisp/eshell/em-cmpl.el b/lisp/eshell/em-cmpl.el
index 4206ad048fa..2439f1ed804 100644
--- a/lisp/eshell/em-cmpl.el
+++ b/lisp/eshell/em-cmpl.el
@@ -306,6 +306,12 @@ to writing a completion function."
     (insert-and-inherit "\t")
     (throw 'pcompleted t)))
 
+(defun eshell-complete--eval-argument-form (arg)
+  "Evaluate a single Eshell argument form ARG for the purposes of completion."
+  (let ((result (eshell-do-eval `(eshell-commands ,arg) t)))
+    (cl-assert (eq (car result) 'quote))
+    (cadr result)))
+
 (defun eshell-complete-parse-arguments ()
   "Parse the command line arguments for `pcomplete-argument'."
   (when (and eshell-no-completion-during-jobs
@@ -344,11 +350,6 @@ to writing a completion function."
     (cl-assert (= (length args) (length posns)))
     (let ((a args) (i 0) new-start)
       (while a
-        ;; Remove any top-level `eshell-splice-args' sigils.  These
-        ;; are meant to be rewritten and can't actually be called.
-        (when (and (consp (car a))
-                   (eq (caar a) 'eshell-splice-args))
-          (setcar a (cadar a)))
         ;; If there's an unreplaced `eshell-operator' sigil, consider
         ;; the token after it the new start of our arguments.
         (when (and (consp (car a))
@@ -364,51 +365,43 @@ to writing a completion function."
               (not (eq (char-before (1- end)) ?\\)))
       (nconc args (list ""))
       (nconc posns (list (point))))
+    ;; Evaluate and expand Eshell forms.
+    (let (evaled-args evaled-posns)
+      (cl-mapc
+       (lambda (arg posn)
+         (pcase arg
+           (`(eshell-splice-args ,val)
+            (dolist (subarg (eshell-complete--eval-argument-form val))
+              (push subarg evaled-args)
+              (push posn evaled-posns)))
+           ((pred listp)
+            (push (eshell-complete--eval-argument-form arg) evaled-args)
+            (push posn evaled-posns))
+           (_
+            (push arg evaled-args)
+            (push posn evaled-posns))))
+       args posns)
+      (setq args (nreverse evaled-args)
+            posns (nreverse evaled-posns)))
+    ;; Convert arguments to forms that Pcomplete can understand.
     (cons (mapcar
            (lambda (arg)
-             (let ((val
-                    (if (listp arg)
-                        (let ((result
-                               (eshell-do-eval
-                                (list 'eshell-commands arg) t)))
-                          (cl-assert (eq (car result) 'quote))
-                          (cadr result))
-                      arg)))
-               (cond ((numberp val)
-                      (setq val (number-to-string val)))
-                     ;; expand .../ etc that only eshell understands to
-                     ;; standard ../../
-                     ((and (stringp val)) (string-match "\\.\\.\\.+/" val)
-                      (setq val (eshell-expand-multiple-dots val))))
-               (or val "")))
+             (pcase arg
+               ;; Expand ".../" etc that only Eshell understands to
+               ;; the standard "../../".
+               ((rx ".." (+ ".") "/")
+                (propertize (eshell-expand-multiple-dots arg)
+                            'pcomplete-arg-value arg))
+               ((pred stringp)
+                arg)
+               ('nil
+                (propertize "" 'pcomplete-arg-value arg))
+               (_
+                (propertize (eshell-stringify arg)
+                            'pcomplete-arg-value arg))))
           args)
          posns)))
 
-(defun eshell--pcomplete-executables ()
-  "Complete amongst a list of directories and executables.
-
-Wrapper for `pcomplete-executables' or `pcomplete-dirs-or-entries',
-depending on the value of `eshell-force-execution'.
-
-Adds path prefix to candidates independent of `action' value."
-  ;; `pcomplete-entries' returns filenames without path on `action' to
-  ;; use current string directory as done in `completion-file-name-table'
-  ;; when `action' is nil to construct executable candidates.
-  (let ((table (if eshell-force-execution
-                   (pcomplete-dirs-or-entries nil #'file-readable-p)
-                 (pcomplete-executables))))
-    (lambda (string pred action)
-      (let ((cands (funcall table string pred action)))
-        (if (eq action t)
-            (let ((specdir (file-name-directory string)))
-              (mapcar
-               (lambda (cand)
-                 (if (stringp cand)
-                     (file-name-concat specdir cand)
-                   cand))
-               cands))
-          cands)))))
-
 (defun eshell--complete-commands-list ()
   "Generate list of applicable, visible commands."
   ;; Building the commands list can take quite a while, especially over Tramp
@@ -419,11 +412,19 @@ Adds path prefix to candidates independent of `action' 
value."
          ;; we complete.  Adjust `pcomplete-stub' accordingly!
         (if (and (> (length pcomplete-stub) 0)
                  (eq (aref pcomplete-stub 0) eshell-explicit-command-char))
-            (setq pcomplete-stub (substring pcomplete-stub 1)))))
-    (completion-table-dynamic
-     (lambda (filename)
-       (if (file-name-directory filename)
-           (eshell--pcomplete-executables)
+             (setq pcomplete-stub (substring pcomplete-stub 1))))
+        (filename (pcomplete-arg)))
+    ;; Do not use `completion-table-dynamic' when completing a command file
+    ;; name since it doesn't know about boundaries and would end up doing silly
+    ;; things like adding a SPC char when completing to "/usr/sbin/".
+    ;;
+    ;; If you work on this function, be careful not to reintroduce bug#48995.
+    (if (file-name-directory filename)
+        (if eshell-force-execution
+            (pcomplete-dirs-or-entries nil #'file-readable-p)
+          (pcomplete-executables))
+      (completion-table-dynamic
+       (lambda (filename)
         (let* ((paths (eshell-get-path))
                (cwd (file-name-as-directory
                      (expand-file-name default-directory)))
diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el
index 99c3d7f627d..b5f1d60ff18 100644
--- a/lisp/eshell/esh-cmd.el
+++ b/lisp/eshell/esh-cmd.el
@@ -343,7 +343,7 @@ This only returns external (non-Lisp) processes."
              #'eshell-complete-lisp-symbols nil t)))
 
 (defun eshell-complete-lisp-symbols ()
-  "If there is a user reference, complete it."
+  "If there is a Lisp symbol, complete it."
   (let ((arg (pcomplete-actual-arg)))
     (when (string-match (concat "\\`" eshell-lisp-regexp) arg)
       (setq pcomplete-stub (substring arg (match-end 0))
diff --git a/lisp/eshell/esh-util.el b/lisp/eshell/esh-util.el
index 544a8a74039..9549e7f1a10 100644
--- a/lisp/eshell/esh-util.el
+++ b/lisp/eshell/esh-util.el
@@ -94,13 +94,6 @@ a non-nil value, will be passed strings, not numbers, even 
when an
 argument matches `eshell-number-regexp'."
   :type 'boolean)
 
-(defcustom eshell-number-regexp "-?\\([0-9]*\\.\\)?[0-9]+\\(e[-0-9.]+\\)?"
-  "Regular expression used to match numeric arguments.
-If `eshell-convert-numeric-arguments' is non-nil, and an argument
-matches this regexp, it will be converted to a Lisp number, using the
-function `string-to-number'."
-  :type 'regexp)
-
 (defcustom eshell-ange-ls-uids nil
   "List of user/host/id strings, used to determine remote ownership."
   :type '(repeat (cons :tag "Host for User/UID map"
@@ -111,6 +104,22 @@ function `string-to-number'."
 
 ;;; Internal Variables:
 
+(defvar eshell-number-regexp
+  (rx (? "-")
+      (or (seq (+ digit) (? "." (* digit)))
+          (seq (* digit) "." (+ digit)))
+      ;; Optional exponent
+      (? (or "e" "E")
+         (or "+INF" "+NaN"
+             (seq (? (or "+" "-")) (+ digit)))))
+  "Regular expression used to match numeric arguments.
+If `eshell-convert-numeric-arguments' is non-nil, and an argument
+matches this regexp, it will be converted to a Lisp number, using the
+function `string-to-number'.")
+
+(defvar eshell-integer-regexp (rx (? "-") (+ digit))
+  "Regular expression used to match integer arguments.")
+
 (defvar eshell-group-names nil
   "A cache to hold the names of groups.")
 
diff --git a/lisp/eshell/esh-var.el b/lisp/eshell/esh-var.el
index 83dd5cb50f5..60aab92b33e 100644
--- a/lisp/eshell/esh-var.el
+++ b/lisp/eshell/esh-var.el
@@ -587,6 +587,9 @@ Possible variable references are:
 
 (defun eshell-parse-indices ()
   "Parse and return a list of index-lists.
+This produces a series of Lisp forms to be processed by
+`eshell-prepare-indices' and ultimately evaluated by
+`eshell-do-eval'.
 
 For example, \"[0 1][2]\" becomes:
   ((\"0\" \"1\") (\"2\"))."
@@ -605,6 +608,36 @@ For example, \"[0 1][2]\" becomes:
          (goto-char (1+ end)))))
     (nreverse indices)))
 
+(defun eshell-parse-index (index)
+  "Parse a single INDEX in string form.
+If INDEX looks like a number, return that number.
+
+If INDEX looks like \"[BEGIN]..[END]\", where BEGIN and END look
+like integers, return a cons cell of BEGIN and END as numbers;
+BEGIN and/or END can be omitted here, in which case their value
+in the cons is nil.
+
+Otherwise (including if INDEX is not a string), return
+the original value of INDEX."
+  (save-match-data
+    (cond
+     ((and (stringp index) (get-text-property 0 'number index))
+      (string-to-number index))
+     ((and (stringp index)
+           (not (text-property-any 0 (length index) 'escaped t index))
+           (string-match (rx string-start
+                             (group-n 1 (? (regexp eshell-integer-regexp)))
+                             ".."
+                             (group-n 2 (? (regexp eshell-integer-regexp)))
+                             string-end)
+                         index))
+      (let ((begin (match-string 1 index))
+            (end (match-string 2 index)))
+        (cons (unless (string-empty-p begin) (string-to-number begin))
+              (unless (string-empty-p end) (string-to-number end)))))
+     (t
+      index))))
+
 (defun eshell-eval-indices (indices)
   "Evaluate INDICES, a list of index-lists generated by 
`eshell-parse-indices'."
   (declare (obsolete eshell-prepare-indices "30.1"))
@@ -716,56 +749,65 @@ For example, to retrieve the second element of a user's 
record in
 '/etc/passwd', the variable reference would look like:
 
   ${grep johnw /etc/passwd}[: 2]"
-  (while indices
-    (let ((refs (car indices)))
-      (when (stringp value)
-       (let (separator (index (caar indices)))
-          (when (and (stringp index)
-                     (not (get-text-property 0 'number index)))
-            (setq separator index
-                  refs (cdr refs)))
-         (setq value (split-string value separator))
-          (unless quoted
-            (setq value (mapcar #'eshell-convert-to-number value)))))
-      (cond
-       ((< (length refs) 0)
-       (error "Invalid array variable index: %s"
-              (eshell-stringify refs)))
-       ((= (length refs) 1)
-       (setq value (eshell-index-value value (car refs))))
-       (t
-       (let ((new-value (list t)))
-         (while refs
-           (nconc new-value
-                  (list (eshell-index-value value
-                                            (car refs))))
-           (setq refs (cdr refs)))
-         (setq value (cdr new-value))))))
-    (setq indices (cdr indices)))
-  value)
+  (dolist (refs indices value)
+    ;; For string values, check if the first index looks like a
+    ;; regexp, and if so, use that to split the string.
+    (when (stringp value)
+      (let (separator (first (car refs)))
+        (when (stringp (eshell-parse-index first))
+          (setq separator first
+                refs (cdr refs)))
+        (setq value (split-string value separator))
+        (unless quoted
+          (setq value (mapcar #'eshell-convert-to-number value)))))
+    (cond
+     ((< (length refs) 0)
+      (error "Invalid array variable index: %s"
+             (eshell-stringify refs)))
+     ((= (length refs) 1)
+      (setq value (eshell-index-value value (car refs))))
+     (t
+      (let (new-value)
+        (dolist (ref refs)
+          (push (eshell-index-value value ref) new-value))
+        (setq value (nreverse new-value)))))))
+
+(pcase-defmacro eshell-index-range (start end)
+  "A pattern that matches an Eshell index range.
+EXPVAL should be a cons cell, with each slot containing either an
+integer or nil.  If this matches, bind the values of the sltos to
+START and END."
+  (list '\` (cons (list '\, `(and (or (pred integerp) (pred null)) ,start))
+                  (list '\, `(and (or (pred integerp) (pred null)) ,end)))))
 
 (defun eshell-index-value (value index)
   "Reference VALUE using the given INDEX."
-  (when (and (stringp index) (get-text-property 0 'number index))
-    (setq index (string-to-number index)))
-  (if (integerp index)
-      (cond
-       ((ring-p value)
-        (if (> index (ring-length value))
-            (error "Index exceeds length of ring")
-          (ring-ref value index)))
-       ((listp value)
-        (if (> index (length value))
-            (error "Index exceeds length of list")
-          (nth index value)))
-       ((vectorp value)
-        (if (> index (length value))
-            (error "Index exceeds length of vector")
-          (aref value index)))
-       (t
-        (error "Invalid data type for indexing")))
-    ;; INDEX is some non-integer value, so treat VALUE as an alist.
-    (cdr (assoc index value))))
+  (let ((parsed-index (eshell-parse-index index)))
+    (if (ring-p value)
+        (pcase parsed-index
+          ((pred integerp)
+           (ring-ref value parsed-index))
+          ((eshell-index-range start end)
+           (let* ((len (ring-length value))
+                  (real-start (mod (or start 0) len))
+                  (real-end (mod (or end len) len)))
+             (when (and (eq real-end 0)
+                        (not (eq end 0)))
+               (setq real-end len))
+             (ring-convert-sequence-to-ring
+              (seq-subseq (ring-elements value) real-start real-end))))
+          (_
+           (error "Invalid index for ring: %s" index)))
+      (pcase parsed-index
+        ((pred integerp)
+         (when (< parsed-index 0)
+           (setq parsed-index (+ parsed-index (length value))))
+         (seq-elt value parsed-index))
+        ((eshell-index-range start end)
+         (seq-subseq value (or start 0) end))
+        (_
+         ;; INDEX is some non-integer value, so treat VALUE as an alist.
+         (cdr (assoc parsed-index value)))))))
 
 ;;;_* Variable name completion
 
diff --git a/lisp/faces.el b/lisp/faces.el
index 3323eab205a..4933b495a6c 100644
--- a/lisp/faces.el
+++ b/lisp/faces.el
@@ -304,7 +304,16 @@ If the optional argument FRAME is given, report on face 
FACE in that frame.
 If FRAME is t, report on the defaults for face FACE (for new frames).
 If FRAME is omitted or nil, use the selected frame."
   (let ((attrs
-        (delq :inherit (mapcar 'car face-attribute-name-alist)))
+         ;; The _value_ of :inherit teaches us nothing about how FACE
+         ;; looks compared to the default face.  Instead, we will ask
+         ;; `face-attribute' to take inheritance into account when
+         ;; examining other attributes.
+         (delq :inherit
+               ;; A difference in extension past EOL only matters when
+               ;; relevant attributes (such as :background) also
+               ;; differ from the default; otherwise this difference
+               ;; is a false positive.
+               (delq :extend (mapcar 'car face-attribute-name-alist))))
        (differs nil))
     (while (and attrs (not differs))
       (let* ((attr (pop attrs))
diff --git a/lisp/gnus/gnus-search.el b/lisp/gnus/gnus-search.el
index 27c71fa6c6a..22c84bc39cf 100644
--- a/lisp/gnus/gnus-search.el
+++ b/lisp/gnus/gnus-search.el
@@ -1330,9 +1330,10 @@ elements are present."
                      (1- nyear)
                    nyear))
          (setq dmonth 1))))
-    (format-time-string
-     "%e-%b-%Y"
-     (encode-time 0 0 0 dday dmonth dyear))))
+    (with-locale-environment "C"
+     (format-time-string
+      "%e-%b-%Y"
+      (encode-time 0 0 0 dday dmonth dyear)))))
 
 (cl-defmethod gnus-search-imap-handle-string ((engine gnus-search-imap)
                                              (str string))
diff --git a/lisp/isearch.el b/lisp/isearch.el
index bb46c89ae20..22e27764127 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -2774,6 +2774,7 @@ With argument, add COUNT copies of the character."
                                           (mapconcat 
'isearch-text-char-description
                                                      string ""))))))))
 
+(defvar emoji--derived)
 (defun isearch-emoji-by-name (&optional count)
   "Read an Emoji name and add it to the search string COUNT times.
 COUNT (interactively, the prefix argument) defaults to 1.
@@ -2782,7 +2783,13 @@ The command accepts Unicode names like \"smiling face\" 
or
   (interactive "p")
   (with-isearch-suspended
    (let ((emoji (with-temp-buffer
-                  (emoji-search)
+                  ;; Derived emoji not supported yet (bug#60740).
+                  ;; So first load `emoji--labels', then `emoji--init'
+                  ;; will not fill `emoji--derived' that is set
+                  ;; to an empty hash table below.
+                  (ignore-errors (require 'emoji-labels))
+                  (let ((emoji--derived (make-hash-table :test #'equal)))
+                    (emoji-search))
                   (if (and (integerp count) (> count 1))
                       (apply 'concat (make-list count (buffer-string)))
                     (buffer-string)))))
diff --git a/lisp/keymap.el b/lisp/keymap.el
index 791221f2459..201a49cef8c 100644
--- a/lisp/keymap.el
+++ b/lisp/keymap.el
@@ -76,12 +76,9 @@ Note that if KEY has a local binding in the current buffer,
 that local binding will continue to shadow any global binding
 that you make with this function."
   (declare (compiler-macro (lambda (form) (keymap--compile-check key) form)))
-  (interactive
-   (let* ((menu-prompting nil)
-          (key (read-key-sequence "Set key globally: " nil t)))
-     (list key
-           (read-command (format "Set key %s to command: "
-                                 (key-description key))))))
+  (interactive "KSet key globally:\nCSet key %s globally to command: ")
+  (unless (stringp key)
+    (setq key (key-description key)))
   (keymap-set (current-global-map) key command))
 
 (defun keymap-local-set (key command)
@@ -94,10 +91,12 @@ KEY is a string that satisfies `key-valid-p'.
 The binding goes in the current buffer's local map, which in most
 cases is shared with all other buffers in the same major mode."
   (declare (compiler-macro (lambda (form) (keymap--compile-check key) form)))
-  (interactive "KSet key locally: \nCSet key %s locally to command: ")
+  (interactive "KSet key locally:\nCSet key %s locally to command: ")
   (let ((map (current-local-map)))
     (unless map
       (use-local-map (setq map (make-sparse-keymap))))
+    (unless (stringp key)
+      (setq key (key-description key)))
     (keymap-set map key command)))
 
 (defun keymap-global-unset (key &optional remove)
@@ -108,7 +107,7 @@ If REMOVE (interactively, the prefix arg), remove the 
binding
 instead of unsetting it.  See `keymap-unset' for details."
   (declare (compiler-macro (lambda (form) (keymap--compile-check key) form)))
   (interactive
-   (list (key-description (read-key-sequence "Set key locally: "))
+   (list (key-description (read-key-sequence "Unset key globally: "))
          current-prefix-arg))
   (keymap-unset (current-global-map) key remove))
 
@@ -291,26 +290,26 @@ See `kbd' for a descripion of KEYS."
       res)))
 
 (defun key-valid-p (keys)
-  "Say whether KEYS is a valid key.
-A key is a string consisting of one or more key strokes.
-The key strokes are separated by single space characters.
+  "Return non-nil if KEYS, a string, is a valid key sequence.
+KEYS should be a string consisting of one or more key strokes,
+with a single space character separating one key stroke from another.
 
 Each key stroke is either a single character, or the name of an
-event, surrounded by angle brackets.  In addition, any key stroke
-may be preceded by one or more modifier keys.  Finally, a limited
-number of characters have a special shorthand syntax.
+event, surrounded by angle brackets <like-this>.  In addition, any
+key stroke may be preceded by one or more modifier keys.  Finally,
+a limited number of characters have a special shorthand syntax.
 
-Here's some example key sequences.
+Here are some example of valid key sequences.
 
   \"f\"           (the key `f')
-  \"S o m\"       (a three key sequence of the keys `S', `o' and `m')
-  \"C-c o\"       (a two key sequence of the keys `c' with the control modifier
-                 and then the key `o')
-  \"H-<left>\"    (the key named \"left\" with the hyper modifier)
+  \"S o m\"       (a three-key sequence of the keys `S', `o' and `m')
+  \"C-c o\"       (a two-key sequence: the key `c' with the control modifier
+                 followed by the key `o')
+  \"H-<left>\"    (the function key named \"left\" with the hyper modifier)
   \"M-RET\"       (the \"return\" key with a meta modifier)
   \"C-M-<space>\" (the \"space\" key with both the control and meta modifiers)
 
-These are the characters that have shorthand syntax:
+These are the characters that have special shorthand syntax:
 NUL, RET, TAB, LFD, ESC, SPC, DEL.
 
 Modifiers have to be specified in this order:
@@ -359,7 +358,7 @@ which is
 This function creates a `keyboard-translate-table' if necessary
 and then modifies one entry in it.
 
-Both KEY and TO are strings that satisfy `key-valid-p'."
+Both KEY and TO should be specified by strings that satisfy `key-valid-p'."
   (declare (compiler-macro
             (lambda (form) (keymap--compile-check from to) form)))
   (keymap--check from)
@@ -370,7 +369,7 @@ Both KEY and TO are strings that satisfy `key-valid-p'."
   (aset keyboard-translate-table (key-parse from) (key-parse to)))
 
 (defun keymap-lookup (keymap key &optional accept-default no-remap position)
-  "Return the binding for command KEY.
+  "Return the binding for command KEY in KEYMAP.
 KEY is a string that satisfies `key-valid-p'.
 
 If KEYMAP is nil, look up in the current keymaps.  If non-nil, it
@@ -392,15 +391,15 @@ in the current keymaps.  However, if the optional third 
argument
 NO-REMAP is non-nil, `keymap-lookup' returns the unmapped
 command.
 
-If KEY is a key sequence initiated with the mouse, the used keymaps
-will depend on the clicked mouse position with regard to the buffer
-and possible local keymaps on strings.
+If KEY is a mouse gesture, the keymaps used depend on the clicked
+mouse position with regards to the buffer, and local keymaps, if any,
+on display and overlay strings.
 
 If the optional argument POSITION is non-nil, it specifies a mouse
 position as returned by `event-start' and `event-end', and the lookup
 occurs in the keymaps associated with it instead of KEY.  It can also
 be a number or marker, in which case the keymap properties at the
-specified buffer position instead of point are used."
+specified buffer position are used instead of point."
   (declare (compiler-macro (lambda (form) (keymap--compile-check key) form)))
   (keymap--check key)
   (when (and keymap position)
@@ -476,7 +475,7 @@ If MESSAGE (and interactively), message the result."
 
 (defun define-keymap (&rest definitions)
   "Create a new keymap and define KEY/DEFINITION pairs as key bindings.
-The new keymap is returned.
+Return the new keymap.
 
 Options can be given as keywords before the KEY/DEFINITION
 pairs.  Available keywords are:
diff --git a/lisp/ldefs-boot.el b/lisp/ldefs-boot.el
index 4d5921582cc..73d47804e5d 100644
--- a/lisp/ldefs-boot.el
+++ b/lisp/ldefs-boot.el
@@ -2919,12 +2919,17 @@ and corresponding effects.
 (register-definition-prefixes "semantic/bovine/c" '("semantic"))
 
 
+;;; Generated autoloads from progmodes/c-ts-common.el
+
+(register-definition-prefixes "c-ts-common" '("c-ts-"))
+
+
 ;;; Generated autoloads from progmodes/c-ts-mode.el
 
 (autoload 'c-ts-base-mode "c-ts-mode" "\
 Major mode for editing C, powered by tree-sitter.
 
-\\{c-ts-mode-map}
+\\{c-ts-base-mode-map}
 
 (fn)" t)
 (autoload 'c-ts-mode "c-ts-mode" "\
@@ -2932,14 +2937,47 @@ Major mode for editing C, powered by tree-sitter.
 
 This mode is independent from the classic cc-mode.el based
 `c-mode', so configuration variables of that mode, like
-`c-basic-offset', don't affect this mode.
+`c-basic-offset', doesn't affect this mode.
+
+To use tree-sitter C/C++ modes by default, evaluate
+
+    (add-to-list \\='major-mode-remap-alist \\='(c-mode . c-ts-mode))
+    (add-to-list \\='major-mode-remap-alist \\='(c++-mode . c++-ts-mode))
+    (add-to-list \\='major-mode-remap-alist
+                 \\='(c-or-c++-mode . c-or-c++-ts-mode))
+
+in your configuration.
 
 (fn)" t)
 (autoload 'c++-ts-mode "c-ts-mode" "\
 Major mode for editing C++, powered by tree-sitter.
 
+This mode is independent from the classic cc-mode.el based
+`c++-mode', so configuration variables of that mode, like
+`c-basic-offset', don't affect this mode.
+
+To use tree-sitter C/C++ modes by default, evaluate
+
+    (add-to-list \\='major-mode-remap-alist \\='(c-mode . c-ts-mode))
+    (add-to-list \\='major-mode-remap-alist \\='(c++-mode . c++-ts-mode))
+    (add-to-list \\='major-mode-remap-alist
+                 \\='(c-or-c++-mode . c-or-c++-ts-mode))
+
+in your configuration.
+
 (fn)" t)
-(register-definition-prefixes "c-ts-mode" '("c-ts-mode-"))
+(autoload 'c-or-c++-ts-mode "c-ts-mode" "\
+Analyze buffer and enable either C or C++ mode.
+
+Some people and projects use .h extension for C++ header files
+which is also the one used for C header files.  This makes
+matching on file name insufficient for detecting major mode that
+should be used.
+
+This function attempts to use file contents to determine whether
+the code is C or C++ and based on that chooses whether to enable
+`c-ts-mode' or `c++-ts-mode'." t)
+(register-definition-prefixes "c-ts-mode" '("c-ts-"))
 
 
 ;;; Generated autoloads from calendar/cal-bahai.el
@@ -4652,7 +4690,6 @@ For use inside Lisp programs, see also 
`c-macro-expansion'.
 
 ;;; Generated autoloads from progmodes/cmake-ts-mode.el
 
-(add-to-list 'auto-mode-alist '("\\(?:CMakeLists\\.txt\\|\\.cmake\\)\\'" . 
cmake-ts-mode))
 (autoload 'cmake-ts-mode "cmake-ts-mode" "\
 Major mode for editing CMake files, powered by tree-sitter.
 
@@ -5635,7 +5672,6 @@ with empty strings removed.
 
 ;;; Generated autoloads from progmodes/csharp-mode.el
 
-(add-to-list 'auto-mode-alist '("\\.cs\\'" . csharp-mode))
 (add-to-list 'auto-mode-alist '("\\.cs\\'" . csharp-mode))
 (autoload 'csharp-mode "csharp-mode" "\
 Major mode for editing Csharp code.
@@ -8011,7 +8047,6 @@ it is disabled.
 
 ;;; Generated autoloads from progmodes/dockerfile-ts-mode.el
 
-(add-to-list 'auto-mode-alist 
'("\\(?:Dockerfile\\(?:\\..*\\)?\\|\\.[Dd]ockerfile\\)\\'" . 
dockerfile-ts-mode))
 (autoload 'dockerfile-ts-mode "dockerfile-ts-mode" "\
 Major mode for editing Dockerfiles, powered by tree-sitter.
 
@@ -9157,7 +9192,7 @@ Turn on EDT Emulation." t)
 
 ;;; Generated autoloads from progmodes/eglot.el
 
-(push (purecopy '(eglot 1 10)) package--builtin-versions)
+(push (purecopy '(eglot 1 11)) package--builtin-versions)
 (autoload 'eglot "eglot" "\
 Start LSP server in support of PROJECT's buffers under MANAGED-MAJOR-MODE.
 
@@ -9195,7 +9230,7 @@ described in `eglot-server-programs', which see.
 LANGUAGE-ID is the language ID string to send to the server for
 MANAGED-MAJOR-MODE, which matters to a minority of servers.
 
-INTERACTIVE is t if called interactively.
+INTERACTIVE is ignored and provided for backward compatibility.
 
 (fn MANAGED-MAJOR-MODE PROJECT CLASS CONTACT LANGUAGE-ID &optional 
INTERACTIVE)" t)
 (autoload 'eglot-ensure "eglot" "\
@@ -14368,12 +14403,12 @@ Add the window configuration CONF to 
`gnus-buffer-configuration'.
 
 ;;; Generated autoloads from progmodes/go-ts-mode.el
 
-(add-to-list 'auto-mode-alist '("\\.go\\'" . go-ts-mode))
 (autoload 'go-ts-mode "go-ts-mode" "\
 Major mode for editing Go, powered by tree-sitter.
 
+\\{go-ts-mode-map}
+
 (fn)" t)
-(add-to-list 'auto-mode-alist '("/go\\.mod\\'" . go-mod-ts-mode))
 (autoload 'go-mod-ts-mode "go-ts-mode" "\
 Major mode for editing go.mod files, powered by tree-sitter.
 
@@ -16205,6 +16240,15 @@ values.
 (register-definition-prefixes "semantic/html" '("semantic-"))
 
 
+;;; Generated autoloads from textmodes/html-ts-mode.el
+
+(autoload 'html-ts-mode "html-ts-mode" "\
+Major mode for editing Html, powered by tree-sitter.
+
+(fn)" t)
+(register-definition-prefixes "html-ts-mode" '("html-ts-mode-"))
+
+
 ;;; Generated autoloads from htmlfontify.el
 
 (push (purecopy '(htmlfontify 0 21)) package--builtin-versions)
@@ -25121,7 +25165,7 @@ Open profile FILENAME.
 
 ;;; Generated autoloads from progmodes/project.el
 
-(push (purecopy '(project 0 9 4)) package--builtin-versions)
+(push (purecopy '(project 0 9 6)) package--builtin-versions)
 (autoload 'project-current "project" "\
 Return the project instance in DIRECTORY, defaulting to `default-directory'.
 
@@ -27362,6 +27406,7 @@ Major mode for editing Ruby code.
 
 ;;; Generated autoloads from progmodes/ruby-ts-mode.el
 
+(push (purecopy '(ruby-ts-mode 0 2)) package--builtin-versions)
 (autoload 'ruby-ts-mode "ruby-ts-mode" "\
 Major mode for editing Ruby, powered by tree-sitter.
 
@@ -27397,7 +27442,6 @@ it is disabled.
 
 ;;; Generated autoloads from progmodes/rust-ts-mode.el
 
-(add-to-list 'auto-mode-alist '("\\.rs\\'" . rust-ts-mode))
 (autoload 'rust-ts-mode "rust-ts-mode" "\
 Major mode for editing Rust, powered by tree-sitter.
 
@@ -33066,8 +33110,6 @@ FRAC should be the inverse of the fractional value; for 
example, a value of
 
 ;;; Generated autoloads from progmodes/typescript-ts-mode.el
 
-(add-to-list 'auto-mode-alist '("\\.ts\\'" . typescript-ts-mode))
-(add-to-list 'auto-mode-alist '("\\.tsx\\'" . tsx-ts-mode))
 (autoload 'typescript-ts-base-mode "typescript-ts-mode" "\
 Major mode for editing TypeScript.
 
@@ -33808,7 +33850,7 @@ is \"www.fsf.co.uk\".
 
 ;;; Generated autoloads from use-package/use-package.el
 
-(push (purecopy '(use-package 2 4 4)) package--builtin-versions)
+(push (purecopy '(use-package 2 4 5)) package--builtin-versions)
 
 
 ;;; Generated autoloads from use-package/use-package-bind-key.el
@@ -34415,7 +34457,8 @@ On a distributed version control system, this runs a 
\"pull\"
 operation on the current branch, prompting for the precise
 command if required.  Optional prefix ARG non-nil forces a prompt
 for the VCS command to run.  If this is successful, a \"push\"
-operation will then be done.
+operation will then be done.  This is supported only in backends
+where the pull operation returns a process.
 
 On a non-distributed version control system, this signals an error.
 It also signals an error in a Bazaar bound branch.
@@ -37012,7 +37055,6 @@ a new xwidget-webkit session, otherwise use an existing 
session.
 
 ;;; Generated autoloads from textmodes/yaml-ts-mode.el
 
-(add-to-list 'auto-mode-alist '("\\.ya?ml\\'" . yaml-ts-mode))
 (autoload 'yaml-ts-mode "yaml-ts-mode" "\
 Major mode for editing YAML, powered by tree-sitter.
 
diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el
index 10f33e5f929..38fd8a4e258 100644
--- a/lisp/net/tramp-adb.el
+++ b/lisp/net/tramp-adb.el
@@ -55,7 +55,7 @@ It is used for TCP/IP devices."
 (defconst tramp-adb-method "adb"
   "When this method name is used, forward all calls to Android Debug Bridge.")
 
-(defcustom tramp-adb-prompt (rx bol (* (not (any "#$\n\r"))) (any "#$") blank)
+(defcustom tramp-adb-prompt (rx bol (* (not (any "#$\r\n"))) (any "#$") blank)
   "Regexp used as prompt in almquist shell."
   :type 'regexp
   :version "28.1"
@@ -1005,17 +1005,19 @@ implementation will be used."
                            ;; file will exist until the process is
                            ;; deleted.
                            (when (bufferp stderr)
-                             (with-current-buffer stderr
-                               (insert-file-contents-literally
-                                remote-tmpstderr 'visit))
+                             (ignore-errors
+                               (with-current-buffer stderr
+                                 (insert-file-contents-literally
+                                  remote-tmpstderr 'visit)))
                              ;; Delete tmpstderr file.
                              (add-function
                               :after (process-sentinel p)
                               (lambda (_proc _msg)
-                                (with-current-buffer stderr
-                                  (insert-file-contents-literally
-                                   remote-tmpstderr 'visit nil nil 'replace))
-                                (delete-file remote-tmpstderr))))
+                                (ignore-errors
+                                  (with-current-buffer stderr
+                                    (insert-file-contents-literally
+                                     remote-tmpstderr 'visit nil nil 'replace))
+                                  (delete-file remote-tmpstderr)))))
                            ;; Return process.
                            p))))
 
diff --git a/lisp/net/tramp-archive.el b/lisp/net/tramp-archive.el
index 7c1f578d085..97adb36c4af 100644
--- a/lisp/net/tramp-archive.el
+++ b/lisp/net/tramp-archive.el
@@ -611,23 +611,22 @@ offered."
 (defun tramp-archive-handle-directory-files
     (directory &optional full match nosort count)
   "Like `directory-files' for Tramp files."
-  (unless (file-exists-p directory)
-    (tramp-error (tramp-dissect-file-name directory) 'file-missing directory))
-  (when (file-directory-p directory)
-    (setq directory (file-name-as-directory (expand-file-name directory)))
-    (let ((temp (nreverse (file-name-all-completions "" directory)))
-         result item)
-
-      (while temp
-       (setq item (directory-file-name (pop temp)))
-       (when (or (null match) (string-match-p match item))
-         (push (if full (concat directory item) item)
-               result)))
-      (unless nosort
-        (setq result (sort result #'string<)))
-      (when (and (natnump count) (> count 0))
-       (setq result (tramp-compat-ntake count result)))
-      result)))
+  (tramp-barf-if-file-missing (tramp-dissect-file-name directory) directory
+    (when (file-directory-p directory)
+      (setq directory (file-name-as-directory (expand-file-name directory)))
+      (let ((temp (nreverse (file-name-all-completions "" directory)))
+           result item)
+
+       (while temp
+         (setq item (directory-file-name (pop temp)))
+         (when (or (null match) (string-match-p match item))
+           (push (if full (concat directory item) item)
+                 result)))
+       (unless nosort
+          (setq result (sort result #'string<)))
+       (when (and (natnump count) (> count 0))
+         (setq result (tramp-compat-ntake count result)))
+       result))))
 
 (defun tramp-archive-handle-dired-uncache (dir)
   "Like `dired-uncache' for file archives."
diff --git a/lisp/net/tramp-container.el b/lisp/net/tramp-container.el
index 1dd29190f10..5ae9ebaefb2 100644
--- a/lisp/net/tramp-container.el
+++ b/lisp/net/tramp-container.el
@@ -121,15 +121,16 @@
   "Tramp method name to use to connect to Toolbox containers.")
 
 ;;;###tramp-autoload
-(defun tramp-docker--completion-function (&rest _args)
-  "List Docker-like containers available for connection.
+(defun tramp-container--completion-function (program)
+  "List running containers available for connection.
+PROGRAM is the program to be run for \"ps\", either
+`tramp-docker-program' or `tramp-podman-program'.
 
 This function is used by `tramp-set-completion-function', please
 see its function help for a description of the format."
   (when-let ((default-directory tramp-compat-temporary-file-directory)
             (raw-list (shell-command-to-string
-                       (concat tramp-docker-program
-                               " ps --format '{{.ID}}\t{{.Names}}'")))
+                       (concat program " ps --format '{{.ID}}\t{{.Names}}'")))
              (lines (split-string raw-list "\n" 'omit))
              (names (mapcar
                     (lambda (line)
@@ -139,7 +140,7 @@ see its function help for a description of the format."
                              line)
                         (or (match-string 2 line) (match-string 1 line))))
                      lines)))
-    (mapcar (lambda (m) (list nil m)) (delq nil names))))
+    (mapcar (lambda (name) (list nil name)) (delq nil names))))
 
 ;;;###tramp-autoload
 (defun tramp-kubernetes--completion-function (&rest _args)
@@ -153,9 +154,7 @@ see its function help for a description of the format."
                                 " get pods --no-headers "
                                 "-o custom-columns=NAME:.metadata.name")))
              (names (split-string raw-list "\n" 'omit)))
-    (mapcar (lambda (name)
-              (list nil name))
-            names)))
+    (mapcar (lambda (name) (list nil name)) (delq nil names))))
 
 (defun tramp-kubernetes--current-context-data (vec)
   "Return Kubernetes current context data as JSON string."
@@ -194,7 +193,7 @@ see its function help for a description of the format."
                              line)
                         (match-string 1 line)))
                      lines)))
-    (mapcar (lambda (m) (list nil m)) (delq nil names))))
+    (mapcar (lambda (name) (list nil name)) (delq nil names))))
 
 ;;;###tramp-autoload
 (defvar tramp-default-remote-shell) ;; Silence byte compiler.
@@ -256,11 +255,13 @@ see its function help for a description of the format."
 
  (tramp-set-completion-function
   tramp-docker-method
-  '((tramp-docker--completion-function "")))
+  `((tramp-container--completion-function
+     ,(executable-find tramp-docker-program))))
 
  (tramp-set-completion-function
   tramp-podman-method
-  '((tramp-docker--completion-function "")))
+  `((tramp-container--completion-function
+     ,(executable-find tramp-podman-program))))
 
  (tramp-set-completion-function
   tramp-kubernetes-method
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index 25bc59eb4ff..d1f723e9807 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -3003,13 +3003,21 @@ implementation will be used."
                              (process-put p 'remote-pid pid)
                              (tramp-set-connection-property
                               p "remote-pid" pid))
-                           ;; Disable carriage return to newline
-                           ;; translation.  This does not work on
-                           ;; macOS, see Bug#50748.
-                           (when (and (memq connection-type '(nil pipe))
-                                      (not
-                                       (tramp-check-remote-uname v "Darwin")))
-                             (tramp-send-command v "stty -icrnl"))
+                           (when (memq connection-type '(nil pipe))
+                             ;; Disable carriage return to newline
+                             ;; translation.  This does not work on
+                             ;; macOS, see Bug#50748.
+                             ;; We must also disable buffering,
+                             ;; otherwise strings larger than 4096
+                             ;; bytes, sent by the process, could
+                             ;; block, see termios(3) and
+                             ;; 
<https://github.com/emacs-lsp/lsp-mode/issues/2375#issuecomment-1407272718>.
+                             ;; FIXME: Shall we rather use "stty raw"?
+                             (if (tramp-check-remote-uname v "Darwin")
+                                 (tramp-send-command
+                                  v "stty -icanon min 1 time 0")
+                               (tramp-send-command
+                                v "stty -icrnl -icanon min 1 time 0")))
                            ;; `tramp-maybe-open-connection' and
                            ;; `tramp-send-command-and-read' could
                            ;; have trashed the connection buffer.
@@ -3877,7 +3885,7 @@ Fall back to normal file name handler if no Tramp handler 
exists."
   "Read output from \"inotifywait\" and add corresponding `file-notify' 
events."
   (let ((events (process-get proc 'events)))
     (tramp-message proc 6 "%S\n%s" proc string)
-    (dolist (line (split-string string "[\n\r]+" 'omit))
+    (dolist (line (split-string string (rx (+ (any "\r\n"))) 'omit))
       ;; Check, whether there is a problem.
       (unless (string-match
               (rx bol (+ (not blank)) (+ blank) (group (+ (not blank)))
diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el
index a9cec17f536..b2272f804e0 100644
--- a/lisp/net/tramp-smb.el
+++ b/lisp/net/tramp-smb.el
@@ -1878,7 +1878,7 @@ If ARGUMENT is non-nil, use it as argument for
          (setq tramp-smb-version (shell-command-to-string command))
          (tramp-message vec 6 command)
          (tramp-message vec 6 "\n%s" tramp-smb-version)
-         (if (string-match (rx (+ (any " \t\n\r")) eos) tramp-smb-version)
+         (if (string-match (rx (+ (any " \t\r\n")) eos) tramp-smb-version)
              (setq tramp-smb-version
                    (replace-match "" nil nil tramp-smb-version))))
 
diff --git a/lisp/net/tramp-sudoedit.el b/lisp/net/tramp-sudoedit.el
index 486a22a60e1..1f646253579 100644
--- a/lisp/net/tramp-sudoedit.el
+++ b/lisp/net/tramp-sudoedit.el
@@ -477,7 +477,7 @@ the result will be a local, non-Tramp, file name."
            "" (file-name-unquote localname)))
        (mapcar
        (lambda (f)
-         (if (file-directory-p (expand-file-name f directory))
+         (if (ignore-errors (file-directory-p (expand-file-name f directory)))
              (file-name-as-directory f)
            f))
        (delq
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 6dca53dcbcf..21dbd40b1d2 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -82,6 +82,7 @@
 (progn
   (defvar tramp--startup-hook nil
     "Forms to be executed at the end of tramp.el.")
+
   (put 'tramp--startup-hook 'tramp-suppress-trace t)
 
   (defmacro tramp--with-startup (&rest body)
@@ -641,7 +642,7 @@ This regexp must match both `tramp-initial-end-of-output' 
and
   (rx
    bol (* nonl)
    (group (regexp (regexp-opt password-word-equivalents)))
-   (* nonl) ":" (? "\^@") (* blank))
+   (* nonl) (any "::៖") (? "\^@") (* blank))
   "Regexp matching password-like prompts.
 The regexp should match at end of buffer.
 
@@ -651,20 +652,19 @@ usually more convenient to add new passphrases to that 
variable
 instead of altering this variable.
 
 The `sudo' program appears to insert a `^@' character into the prompt."
-  :version "24.4"
+  :version "29.1"
   :type 'regexp)
 
 (defcustom tramp-wrong-passwd-regexp
   (rx bol (* nonl)
       (| "Permission denied"
-        (: "Login " (| "Incorrect" "incorrect"))
-        "Connection refused"
-        "Connection closed"
         "Timeout, server not responding."
         "Sorry, try again."
         "Name or service not known"
         "Host key verification failed."
         "No supported authentication methods left to try!"
+        (: "Login " (| "Incorrect" "incorrect"))
+        (: "Connection " (| "refused" "closed"))
         (: "Received signal " (+ digit)))
       (* nonl))
   "Regexp matching a `login failed' message.
@@ -787,6 +787,7 @@ It shall be used in combination with 
`generate-new-buffer-name'.")
 (defvar tramp-temp-buffer-file-name nil
   "File name of a persistent local temporary file.
 Useful for \"rsync\" like methods.")
+
 (make-variable-buffer-local 'tramp-temp-buffer-file-name)
 (put 'tramp-temp-buffer-file-name 'permanent-local t)
 
@@ -1404,6 +1405,7 @@ the (optional) timestamp of last activity on this 
connection.")
   "Password save function.
 Will be called once the password has been verified by successful
 authentication.")
+
 (put 'tramp-password-save-function 'tramp-suppress-trace t)
 
 (defvar tramp-password-prompt-not-unique nil
@@ -2299,12 +2301,12 @@ the resulting error message."
          (progn ,@body)
        (error (tramp-message ,vec-or-proc 3 ,format ,err) nil))))
 
-;; This macro shall optimize the cases where an `file-exists-p' call
-;; is invoked first.  Often, the file exists, so the remote command is
+;; This macro shall optimize the cases where a `file-exists-p' call is
+;; invoked first.  Often, the file exists, so the remote command is
 ;; superfluous.
 (defmacro tramp-barf-if-file-missing (vec filename &rest body)
   "Execute BODY and return the result.
-In case if an error, raise a `file-missing' error if FILENAME
+In case of an error, raise a `file-missing' error if FILENAME
 does not exist, otherwise propagate the error."
   (declare (indent 2) (debug (symbolp form body)))
   (let ((err (make-symbol "err")))
@@ -2456,13 +2458,14 @@ Example:
        (setcdr v (delete (car v) (cdr v))))
       ;; Check for function and file or registry key.
       (unless (and (functionp (nth 0 (car v)))
+                  (stringp (nth 1 (car v)))
                   (cond
                    ;; Windows registry.
                    ((string-prefix-p "HKEY_CURRENT_USER" (nth 1 (car v)))
                     (and (memq system-type '(cygwin windows-nt))
                          (zerop
                           (tramp-call-process
-                           v "reg" nil nil nil "query" (nth 1 (car v))))))
+                           nil "reg" nil nil nil "query" (nth 1 (car v))))))
                    ;; DNS-SD service type.
                    ((string-match-p
                      tramp-dns-sd-service-regexp (nth 1 (car v))))
@@ -3935,9 +3938,10 @@ Let-bind it when necessary.")
 (defun tramp-handle-file-directory-p (filename)
   "Like `file-directory-p' for Tramp files."
   ;; `file-truename' could raise an error, for example due to a cyclic
-  ;; symlink.
-  (ignore-errors
-    (eq (file-attribute-type (file-attributes (file-truename filename))) t)))
+  ;; symlink.  We don't protect this despite it, because other errors
+  ;; might be worth to be visible, for example impossibility to mount
+  ;; in tramp-gvfs.el.
+  (eq (file-attribute-type (file-attributes (file-truename filename))) t))
 
 (defun tramp-handle-file-equal-p (filename1 filename2)
   "Like `file-equalp-p' for Tramp files."
@@ -4938,7 +4942,7 @@ substitution.  SPEC-LIST is a list of char/value pairs 
used for
                :command (append `(,login-program) login-args command)
                :coding coding :noquery noquery :connection-type connection-type
                :sentinel sentinel :stderr stderr))
-           ;; Set filter.  Prior Emacs 29.1, it doesn't work reliable
+           ;; Set filter.  Prior Emacs 29.1, it doesn't work reliably
            ;; to provide it as `make-process' argument when filter is
            ;; t.  See Bug#51177.
            (when filter
@@ -5152,17 +5156,19 @@ support symbolic links."
                  (add-function
                   :after (process-sentinel p)
                   (lambda (_proc _string)
-                    (with-current-buffer error-buffer
-                      (insert-file-contents-literally
-                       error-file nil nil nil 'replace))
-                    (delete-file error-file))))
+                    (ignore-errors
+                      (with-current-buffer error-buffer
+                        (insert-file-contents-literally
+                         error-file nil nil nil 'replace))
+                      (delete-file error-file)))))
                (display-buffer output-buffer '(nil (allow-no-window . t)))))
 
            ;; Insert error messages if they were separated.
            (when (and error-file (not (process-live-p p)))
-             (with-current-buffer error-buffer
-               (insert-file-contents-literally error-file))
-             (delete-file error-file))))
+             (ignore-errors
+               (with-current-buffer error-buffer
+                 (insert-file-contents-literally error-file))
+               (delete-file error-file)))))
 
       ;; Synchronous case.
       (prog1
@@ -5170,9 +5176,10 @@ support symbolic links."
          (process-file-shell-command command nil buffer)
        ;; Insert error messages if they were separated.
        (when error-file
-         (with-current-buffer error-buffer
-           (insert-file-contents-literally error-file))
-         (delete-file error-file))
+         (ignore-errors
+           (with-current-buffer error-buffer
+             (insert-file-contents-literally error-file))
+           (delete-file error-file)))
        (if current-buffer-p
            ;; This is like exchange-point-and-mark, but doesn't
            ;; activate the mark.  It is cleaner to avoid activation,
diff --git a/lisp/org/ChangeLog.1 b/lisp/org/ChangeLog.1
index eb126df6334..a4eae350d98 100644
--- a/lisp/org/ChangeLog.1
+++ b/lisp/org/ChangeLog.1
@@ -30500,7 +30500,7 @@
 
        * org.el (org-make-tags-matcher): Never use IDO for completing the
        tags matcher match string.
-       (org-completing-read): Also remove the special biding for "?".
+       (org-completing-read): Also remove the special binding for "?".
 
        * org-attach.el (org-attach-allow-inheritance): New option.
        (org-attach-inherited): New variable.
diff --git a/lisp/org/org-agenda.el b/lisp/org/org-agenda.el
index 2d194ad3413..63107e8e6a4 100644
--- a/lisp/org/org-agenda.el
+++ b/lisp/org/org-agenda.el
@@ -3474,13 +3474,17 @@ This ensures the export commands can easily use it."
     (when (setq tmp (plist-get props 'date))
       (when (integerp tmp) (setq tmp (calendar-gregorian-from-absolute tmp)))
       (let ((calendar-date-display-form
-             '(year "-" (string-pad month 2 ?0 'left) "-" (string-pad day 2 ?0 
'left))))
+             '((format "%s-%.2d-%.2d" year
+                       (string-to-number month)
+                       (string-to-number day)))))
        (setq tmp (calendar-date-string tmp)))
       (setq props (plist-put props 'date tmp)))
     (when (setq tmp (plist-get props 'day))
       (when (integerp tmp) (setq tmp (calendar-gregorian-from-absolute tmp)))
       (let ((calendar-date-display-form
-             '(year "-" (string-pad month 2 ?0 'left) "-" (string-pad day 2 ?0 
'left))))
+             '((format "%s-%.2d-%.2d" year
+                       (string-to-number month)
+                       (string-to-number day)))))
        (setq tmp (calendar-date-string tmp)))
       (setq props (plist-put props 'day tmp))
       (setq props (plist-put props 'agenda-day tmp)))
diff --git a/lisp/org/org-macs.el b/lisp/org/org-macs.el
index 07c668a807d..8d7b0b034f8 100644
--- a/lisp/org/org-macs.el
+++ b/lisp/org/org-macs.el
@@ -46,7 +46,7 @@
   ;; `org-git-version' check because the generated Org version strings
   ;; will not match.
   `(unless (equal (org-release) ,(org-release))
-     (warn "Org version mismatch.  Make sure that correct `load-path' is set 
early in init.el
+     (warn "Org version mismatch.  Org loading aborted.
 This warning usually appears when a built-in Org version is loaded
 prior to the more recent Org version.
 
diff --git a/lisp/org/org-version.el b/lisp/org/org-version.el
index 22f952d7a30..8372a0be4a5 100644
--- a/lisp/org/org-version.el
+++ b/lisp/org/org-version.el
@@ -11,7 +11,7 @@ Inserted by installing Org mode or when a release is made."
 (defun org-git-version ()
   "The Git version of Org mode.
 Inserted by installing Org or when a release is made."
-   (let ((org-git-version "release_9.6.1-16-ge37e9b"))
+   (let ((org-git-version "release_9.6.1-23-gc45a05"))
      org-git-version))
 
 (provide 'org-version)
diff --git a/lisp/org/org.el b/lisp/org/org.el
index 153e860f9a5..1b829d837c7 100644
--- a/lisp/org/org.el
+++ b/lisp/org/org.el
@@ -8608,6 +8608,7 @@ or to another Org file, automatically push the old 
position onto the ring."
 (defvar org-agenda-buffer-name)
 (defun org-follow-timestamp-link ()
   "Open an agenda view for the time-stamp date/range at point."
+  (require 'org-agenda)
   ;; Avoid changing the global value.
   (let ((org-agenda-buffer-name org-agenda-buffer-name))
     (cond
diff --git a/lisp/org/ox.el b/lisp/org/ox.el
index 65f9ff18279..6f819def93a 100644
--- a/lisp/org/ox.el
+++ b/lisp/org/ox.el
@@ -6600,14 +6600,14 @@ see.
 Optional argument POST-PROCESS is a function which should accept
 no argument.  It is always called within the current process,
 from BUFFER, with point at its beginning.  Export back-ends can
-use it to set a major mode there, e.g,
+use it to set a major mode there, e.g.,
 
   (defun org-latex-export-as-latex
     (&optional async subtreep visible-only body-only ext-plist)
     (interactive)
     (org-export-to-buffer \\='latex \"*Org LATEX Export*\"
       async subtreep visible-only body-only ext-plist
-      #'LaTeX-mode))
+      #\\='LaTeX-mode))
 
 When expressed as an anonymous function, using `lambda',
 POST-PROCESS needs to be quoted.
diff --git a/lisp/progmodes/c-ts-common.el b/lisp/progmodes/c-ts-common.el
index 6671d4be5b6..8729cae4ba7 100644
--- a/lisp/progmodes/c-ts-common.el
+++ b/lisp/progmodes/c-ts-common.el
@@ -2,7 +2,7 @@
 
 ;; Copyright (C) 2023 Free Software Foundation, Inc.
 
-;; Author     : 付禹安 (Yuan Fu) <casouri@gmail.com>
+;; Maintainer : 付禹安 (Yuan Fu) <casouri@gmail.com>
 ;; Keywords   : c c++ java javascript rust languages tree-sitter
 
 ;; This file is part of GNU Emacs.
@@ -22,7 +22,10 @@
 
 ;;; Commentary:
 ;;
-;; For C-like language major modes:
+;; This file contains functions that can be shared by C-like language
+;; major modes, like indenting and filling "/* */" block comments.
+;;
+;; For indenting and filling comments:
 ;;
 ;; - Use `c-ts-common-comment-setup' to setup comment variables and
 ;;   filling.
@@ -30,6 +33,14 @@
 ;; - Use simple-indent matcher `c-ts-common-looking-at-star' and
 ;;   anchor `c-ts-common-comment-start-after-first-star' for indenting
 ;;   block comments.  See `c-ts-mode--indent-styles' for example.
+;;
+;; For indenting statements:
+;;
+;; - Set `c-ts-common-indent-offset',
+;;   `c-ts-common-indent-block-type-regexp', and
+;;   `c-ts-common-indent-bracketless-type-regexp', then use simple-indent
+;;   offset `c-ts-common-statement-offset' in
+;;   `treesit-simple-indent-rules'.
 
 ;;; Code:
 
@@ -39,6 +50,9 @@
 (declare-function treesit-node-start "treesit.c")
 (declare-function treesit-node-end "treesit.c")
 (declare-function treesit-node-type "treesit.c")
+(declare-function treesit-node-parent "treesit.c")
+
+;;; Comment indentation and filling
 
 (defun c-ts-common-looking-at-star (_n _p bol &rest _)
   "A tree-sitter simple indent matcher.
@@ -180,7 +194,8 @@ comment."
       (when end-marker
         (goto-char end-marker)
         (delete-region (point) (+ end-len (point)))
-        (insert (make-string end-len ?\s))))))
+        (insert (make-string end-len ?\s)))
+      (goto-char orig-point))))
 
 (defun c-ts-common-comment-setup ()
   "Set up local variables for C-like comment.
@@ -242,6 +257,103 @@ Set up:
   (setq-local paragraph-separate paragraph-start)
   (setq-local fill-paragraph-function #'c-ts-common--fill-paragraph))
 
+;;; Statement indent
+
+(defvar c-ts-common-indent-offset nil
+  "Indent offset used by `c-ts-common' indent functions.
+
+This should be the symbol of the indent offset variable for the
+particular major mode.  This cannot be nil for `c-ts-common'
+statement indent functions to work.")
+
+(defvar c-ts-common-indent-block-type-regexp nil
+  "Regexp matching types of block nodes (i.e., {} blocks).
+
+This cannot be nil for `c-ts-common' statement indent functions
+to work.")
+
+(defvar c-ts-common-indent-bracketless-type-regexp nil
+  "A regexp matching types of bracketless constructs.
+
+These constructs include if, while, do-while, for statements.  In
+these statements, the body can omit the bracket, which requires
+special handling from our bracket-counting indent algorithm.
+
+This can be nil, meaning such special handling is not needed.")
+
+(defun c-ts-common-statement-offset (node parent bol &rest _)
+  "This anchor is used for children of a statement inside a block.
+
+This function basically counts the number of block nodes (i.e.,
+brackets) (defined by `c-ts-mode--indent-block-type-regexp')
+between NODE and the root node (not counting NODE itself), and
+multiply that by `c-ts-common-indent-offset'.
+
+To support GNU style, on each block level, this function also
+checks whether the opening bracket { is on its own line, if so,
+it adds an extra level, except for the top-level.
+
+PARENT is NODE's parent, BOL is the beginning of non-whitespace
+characters on the current line."
+  (let ((level 0))
+    ;; If NODE is a opening/closing bracket on its own line, take off
+    ;; one level because the code below assumes NODE is a statement
+    ;; _inside_ a {} block.
+    (when (and node
+               (or (string-match-p c-ts-common-indent-block-type-regexp
+                                   (treesit-node-type node))
+                   (save-excursion (goto-char bol) (looking-at-p "}"))))
+      (cl-decf level))
+    ;; If point is on an empty line, NODE would be nil, but we pretend
+    ;; there is a statement node.
+    (when (null node)
+      (setq node t))
+    ;; Go up the tree and compute indent level.
+    (while (if (eq node t)
+               (setq node parent)
+             node)
+      (when (string-match-p c-ts-common-indent-block-type-regexp
+                            (treesit-node-type node))
+        (cl-incf level)
+        (save-excursion
+          (goto-char (treesit-node-start node))
+          ;; Add an extra level if the opening bracket is on its own
+          ;; line, except (1) it's at top-level, or (2) it's immediate
+          ;; parent is another block.
+          (cond ((bolp) nil) ; Case (1).
+                ((let ((parent-type (treesit-node-type
+                                     (treesit-node-parent node))))
+                   ;; Case (2).
+                   (and parent-type
+                        (string-match-p
+                         c-ts-common-indent-block-type-regexp
+                         parent-type)))
+                 nil)
+                ;; Add a level.
+                ((looking-back (rx bol (* whitespace))
+                               (line-beginning-position))
+                 (cl-incf level)))))
+      (setq level (c-ts-mode--fix-bracketless-indent level node))
+      ;; Go up the tree.
+      (setq node (treesit-node-parent node)))
+    (* level (symbol-value c-ts-common-indent-offset))))
+
+(defun c-ts-mode--fix-bracketless-indent (level node)
+  "Takes LEVEL and NODE and return adjusted LEVEL.
+This fixes indentation for cases shown in bug#61026.  Basically
+in C-like syntax, statements like if, for, while sometimes omit
+the bracket in the body."
+  (let ((block-re c-ts-common-indent-block-type-regexp)
+        (statement-re
+         c-ts-common-indent-bracketless-type-regexp)
+        (node-type (treesit-node-type node))
+        (parent-type (treesit-node-type (treesit-node-parent node))))
+    (if (and block-re statement-re node-type parent-type
+             (not (string-match-p block-re node-type))
+             (string-match-p statement-re parent-type))
+        (1+ level)
+      level)))
+
 (provide 'c-ts-common)
 
 ;;; c-ts-common.el ends here
diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el
index 1f22a2b2a64..586849e9a3d 100644
--- a/lisp/progmodes/c-ts-mode.el
+++ b/lisp/progmodes/c-ts-mode.el
@@ -63,11 +63,6 @@
 ;; will set up Emacs to use the C/C++ modes defined here for other
 ;; files, provided that you have the corresponding parser grammar
 ;; libraries installed.
-;;
-;; - Use variable `c-ts-mode-indent-block-type-regexp' with indent
-;;   offset c-ts-mode--statement-offset for indenting statements.
-;;   Again, see `c-ts-mode--indent-styles' for example.
-;;
 
 ;;; Code:
 
@@ -92,6 +87,27 @@
   :safe 'integerp
   :group 'c)
 
+(defun c-ts-mode--indent-style-setter (sym val)
+  "Custom setter for `c-ts-mode-set-style'.
+Apart from setting the default value of SYM to VAL, also change
+the value of SYM in `c-ts-mode' and `c++-ts-mode' buffers to VAL."
+  (set-default sym val)
+  (named-let loop ((res nil)
+                   (buffers (buffer-list)))
+    (if (null buffers)
+        (mapc (lambda (b)
+                (with-current-buffer b
+                  (setq-local treesit-simple-indent-rules
+                              (treesit--indent-rules-optimize
+                               (c-ts-mode--get-indent-style
+                                (if (derived-mode-p 'c-ts-mode) 'c 'cpp))))))
+              res)
+      (let ((buffer (car buffers)))
+        (with-current-buffer buffer
+          (if (derived-mode-p 'c-ts-mode 'c++-ts-mode)
+              (loop (append res (list buffer)) (cdr buffers))
+            (loop res (cdr buffers))))))))
+
 (defcustom c-ts-mode-indent-style 'gnu
   "Style used for indentation.
 
@@ -100,13 +116,51 @@ one of the supplied styles doesn't suffice a function 
could be
 set instead.  This function is expected return a list that
 follows the form of `treesit-simple-indent-rules'."
   :version "29.1"
-  :type '(choice (symbol :tag "Gnu" 'gnu)
-                 (symbol :tag "K&R" 'k&r)
-                 (symbol :tag "Linux" 'linux)
-                 (symbol :tag "BSD" 'bsd)
+  :type '(choice (symbol :tag "Gnu" gnu)
+                 (symbol :tag "K&R" k&r)
+                 (symbol :tag "Linux" linux)
+                 (symbol :tag "BSD" bsd)
                  (function :tag "A function for user customized style" ignore))
+  :set #'c-ts-mode--indent-style-setter
   :group 'c)
 
+(defun c-ts-mode--get-indent-style (mode)
+  "Helper function to set indentation style.
+MODE is either `c' or `cpp'."
+  (let ((style
+         (if (functionp c-ts-mode-indent-style)
+             (funcall c-ts-mode-indent-style)
+           (alist-get c-ts-mode-indent-style (c-ts-mode--indent-styles 
mode)))))
+    `((,mode ,@style))))
+
+(defun c-ts-mode--prompt-for-style ()
+  "Prompt for a indent style and return the symbol for it."
+  (let ((mode (if (derived-mode-p 'c-ts-mode) 'c 'c++)))
+    (intern
+     (completing-read
+      "Style: "
+      (mapcar #'car (c-ts-mode--indent-styles mode))
+      nil t nil nil "gnu"))))
+
+(defun c-ts-mode-set-style (style)
+  "Set the indent style of C/C++ modes globally to STYLE.
+
+This changes the current indent style of every C/C++ buffer and
+the default C/C++ indent style in this Emacs session."
+  (interactive (list (c-ts-mode--prompt-for-style)))
+  (c-ts-mode--indent-style-setter 'c-ts-mode-indent-style style))
+
+(defun c-ts-mode-set-local-style (style)
+  "Set the C/C++ indent style of the current buffer to STYLE."
+  (interactive (list (c-ts-mode--prompt-for-style)))
+  (if (not (derived-mode-p 'c-ts-mode 'c++-ts-mode))
+      (user-error "The current buffer is not in `c-ts-mode' nor `c++-ts-mode'")
+    (setq-local c-ts-mode-indent-style style)
+    (setq treesit-simple-indent-rules
+          (treesit--indent-rules-optimize
+           (c-ts-mode--get-indent-style
+            (if (derived-mode-p 'c-ts-mode) 'c 'cpp))))))
+
 ;;; Syntax table
 
 (defvar c-ts-mode--syntax-table
@@ -177,7 +231,7 @@ MODE is either `c' or `cpp'."
            ;; Labels.
            ((node-is "labeled_statement") parent-bol 0)
            ((parent-is "labeled_statement")
-            point-min c-ts-mode--statement-offset)
+            point-min c-ts-common-statement-offset)
 
            ((match "preproc_ifdef" "compound_statement") point-min 0)
            ((match "#endif" "preproc_ifdef") point-min 0)
@@ -186,15 +240,6 @@ MODE is either `c' or `cpp'."
            ((match "preproc_function_def" "compound_statement") point-min 0)
            ((match "preproc_call" "compound_statement") point-min 0)
 
-           ;; {} blocks.
-           ((node-is "}") point-min c-ts-mode--close-bracket-offset)
-           ((parent-is "compound_statement")
-            point-min c-ts-mode--statement-offset)
-           ((parent-is "enumerator_list")
-            point-min c-ts-mode--statement-offset)
-           ((parent-is "field_declaration_list")
-            point-min c-ts-mode--statement-offset)
-
            ((parent-is "function_definition") parent-bol 0)
            ((parent-is "conditional_expression") first-sibling 0)
            ((parent-is "assignment_expression") parent-bol 
c-ts-mode-indent-offset)
@@ -215,13 +260,20 @@ MODE is either `c' or `cpp'."
                  ;; Indent the body of namespace definitions.
                  ((parent-is "declaration_list") parent-bol 
c-ts-mode-indent-offset)))
 
+           ;; int[5] a = { 0, 0, 0, 0 };
            ((parent-is "initializer_list") parent-bol c-ts-mode-indent-offset)
-           ((parent-is "if_statement") parent-bol c-ts-mode-indent-offset)
-           ((parent-is "for_statement") parent-bol c-ts-mode-indent-offset)
-           ((parent-is "while_statement") parent-bol c-ts-mode-indent-offset)
-           ((parent-is "switch_statement") parent-bol c-ts-mode-indent-offset)
-           ((parent-is "case_statement") parent-bol c-ts-mode-indent-offset)
-           ((parent-is "do_statement") parent-bol c-ts-mode-indent-offset)
+           ;; Statement in enum.
+           ((parent-is "enumerator_list") point-min 
c-ts-common-statement-offset)
+           ;; Statement in struct and union.
+           ((parent-is "field_declaration_list") point-min 
c-ts-common-statement-offset)
+
+           ;; Statement in {} blocks.
+           ((parent-is "compound_statement") point-min 
c-ts-common-statement-offset)
+           ;; Closing bracket.
+           ((node-is "}") point-min c-ts-common-statement-offset)
+           ;; Opening bracket.
+           ((node-is "compound_statement") point-min 
c-ts-common-statement-offset)
+
            ,@(when (eq mode 'cpp)
                `(((node-is "field_initializer_list") parent-bol ,(* 
c-ts-mode-indent-offset 2)))))))
     `((gnu
@@ -249,19 +301,6 @@ MODE is either `c' or `cpp'."
        ((parent-is "do_statement") parent-bol 0)
        ,@common))))
 
-(defun c-ts-mode--set-indent-style (mode)
-  "Helper function to set indentation style.
-MODE is either `c' or `cpp'."
-  (let ((style
-         (if (functionp c-ts-mode-indent-style)
-             (funcall c-ts-mode-indent-style)
-           (pcase c-ts-mode-indent-style
-             ('gnu   (alist-get 'gnu (c-ts-mode--indent-styles mode)))
-             ('k&r   (alist-get 'k&r (c-ts-mode--indent-styles mode)))
-             ('bsd   (alist-get 'bsd (c-ts-mode--indent-styles mode)))
-             ('linux (alist-get 'linux (c-ts-mode--indent-styles mode)))))))
-    `((,mode ,@style))))
-
 (defun c-ts-mode--top-level-label-matcher (node &rest _)
   "A matcher that matches a top-level label.
 NODE should be a labeled_statement."
@@ -273,90 +312,6 @@ NODE should be a labeled_statement."
                 "labeled_statement")
          (not (treesit-node-top-level func "compound_statement")))))
 
-(defvar c-ts-mode-indent-block-type-regexp
-  (rx (or "compound_statement"
-          "field_declaration_list"
-          "enumerator_list"))
-  "Regexp matching types of block nodes (i.e., {} blocks).")
-
-(defvar c-ts-mode--statement-offset-post-processr nil
-  "A functions that makes adjustments to `c-ts-mode--statement-offset'.
-
-This is a function that takes two arguments, the current indent
-level and the current node, and returns a new level.
-
-When `c-ts-mode--statement-offset' runs and go up the parse tree,
-it increments the indent level when some condition are met in
-each level.  At each level, after (possibly) incrementing the
-offset, it calls this function, passing it the current indent
-level and the current node, and use the return value as the new
-indent level.")
-
-(defun c-ts-mode--statement-offset (node parent &rest _)
-  "This anchor is used for children of a statement inside a block.
-
-This function basically counts the number of block nodes (defined
-by `c-ts-mode--indent-block-type-regexp') between NODE and the
-root node (not counting NODE itself), and multiply that by
-`c-ts-mode-indent-offset'.
-
-To support GNU style, on each block level, this function also
-checks whether the opening bracket { is on its own line, if so,
-it adds an extra level, except for the top-level.
-
-PARENT is NODE's parent."
-  (let ((level 0))
-    ;; If point is on an empty line, NODE would be nil, but we pretend
-    ;; there is a statement node.
-    (when (null node)
-      (setq node t))
-    (while (if (eq node t)
-               (setq node parent)
-             (setq node (treesit-node-parent node)))
-      (when (string-match-p c-ts-mode-indent-block-type-regexp
-                            (treesit-node-type node))
-        (cl-incf level)
-        (save-excursion
-          (goto-char (treesit-node-start node))
-          ;; Add an extra level if the opening bracket is on its own
-          ;; line, except (1) it's at top-level, or (2) it's immedate
-          ;; parent is another block.
-          (cond ((bolp) nil) ; Case (1).
-                ((let ((parent-type (treesit-node-type
-                                     (treesit-node-parent node))))
-                   ;; Case (2).
-                   (and parent-type
-                        (string-match-p c-ts-mode-indent-block-type-regexp
-                                        parent-type)))
-                 nil)
-                ;; Add a level.
-                ((looking-back (rx bol (* whitespace))
-                               (line-beginning-position))
-                 (cl-incf level)))))
-      (when c-ts-mode--statement-offset-post-processr
-        (setq level (funcall c-ts-mode--statement-offset-post-processr
-                             level node))))
-    (* level c-ts-mode-indent-offset)))
-
-(defun c-ts-mode--fix-bracketless-indent (level node)
-  "Takes LEVEL and NODE and returns adjusted LEVEL.
-This fixes indentation for cases shown in bug#61026.  Basically
-in C/C++, constructs like if, for, while sometimes don't have
-bracket."
-  (if (and (not (equal (treesit-node-type node) "compound_statement"))
-           (member (treesit-node-type (treesit-node-parent node))
-                   '("if_statement" "while_statement" "do_statement"
-                     "for_statement")))
-      (1+ level)
-    level))
-
-(defun c-ts-mode--close-bracket-offset (node parent &rest _)
-  "Offset for the closing bracket, NODE.
-It's basically one level less that the statements in the block.
-PARENT is NODE's parent."
-  (- (c-ts-mode--statement-offset node parent)
-     c-ts-mode-indent-offset))
-
 ;;; Font-lock
 
 (defvar c-ts-mode--preproc-keywords
@@ -754,16 +709,17 @@ the semicolon.  This function skips the semicolon."
 
 ;;; Modes
 
-(defvar-keymap c-ts-mode-map
-  :doc "Keymap for the C language with tree-sitter"
+(defvar-keymap c-ts-base-mode-map
+  :doc "Keymap for C and C-like languages with tree-sitter"
   :parent prog-mode-map
-  "C-c C-q" #'c-ts-mode-indent-defun)
+  "C-c C-q" #'c-ts-mode-indent-defun
+  "C-c ." #'c-ts-mode-set-style)
 
 ;;;###autoload
 (define-derived-mode c-ts-base-mode prog-mode "C"
   "Major mode for editing C, powered by tree-sitter.
 
-\\{c-ts-mode-map}"
+\\{c-ts-base-mode-map}"
   :syntax-table c-ts-mode--syntax-table
 
   ;; Navigation.
@@ -817,8 +773,14 @@ the semicolon.  This function skips the semicolon."
   ;; Indent.
   (when (eq c-ts-mode-indent-style 'linux)
     (setq-local indent-tabs-mode t))
-  (setq-local c-ts-mode--statement-offset-post-processr
-              #'c-ts-mode--fix-bracketless-indent)
+  (setq-local c-ts-common-indent-offset 'c-ts-mode-indent-offset)
+  (setq-local c-ts-common-indent-block-type-regexp
+              (rx (or "compound_statement"
+                      "field_declaration_list"
+                      "enumerator_list")))
+  (setq-local c-ts-common-indent-bracketless-type-regexp
+              (rx (or "if_statement" "do_statement"
+                      "for_statement" "while_statement")))
 
   ;; Comment
   (c-ts-common-comment-setup)
@@ -871,9 +833,11 @@ in your configuration."
     (setq-local comment-end " */")
     ;; Indent.
     (setq-local treesit-simple-indent-rules
-                (c-ts-mode--set-indent-style 'c))
+                (c-ts-mode--get-indent-style 'c))
     ;; Font-lock.
     (setq-local treesit-font-lock-settings (c-ts-mode--font-lock-settings 'c))
+    ;; Navigation.
+    (setq-local treesit-defun-tactic 'top-level)
     (treesit-major-mode-setup)))
 
 ;;;###autoload
@@ -907,7 +871,7 @@ in your configuration."
 
     ;; Indent.
     (setq-local treesit-simple-indent-rules
-                (c-ts-mode--set-indent-style 'cpp))
+                (c-ts-mode--get-indent-style 'cpp))
 
     ;; Font-lock.
     (setq-local treesit-font-lock-settings (c-ts-mode--font-lock-settings 
'cpp))
diff --git a/lisp/progmodes/cc-defs.el b/lisp/progmodes/cc-defs.el
index bdbc03e7c94..aa6f33e9cab 100644
--- a/lisp/progmodes/cc-defs.el
+++ b/lisp/progmodes/cc-defs.el
@@ -1994,7 +1994,7 @@ when it's needed.  The default is the current language 
taken from
            ;; doesn't occur in any word in LIST.  Append it to all
            ;; the alternatives where we want to add \>.  Run through
            ;; `regexp-opt' and then replace it with \>.
-           (let ((unique "") pos)
+           (let ((unique "") (list1 (copy-tree list)) pos)
              (while (let (found)
                       (setq unique (concat unique "@")
                             pos list)
@@ -2005,13 +2005,12 @@ when it's needed.  The default is the current language 
taken from
                                     t))
                         (setq pos (cdr pos)))
                       found))
-             (setq pos (copy-tree list)
-                   )
+             (setq pos list1)
              (while pos
                (if (string-match "\\w\\'" (car pos))
                    (setcar pos (concat (car pos) unique)))
                (setq pos (cdr pos)))
-             (setq re (regexp-opt list))
+             (setq re (regexp-opt list1))
              (setq pos 0)
              (while (string-match unique re pos)
                (setq pos (+ (match-beginning 0) 2)
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index f1e93c1c23c..1899b522ab0 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -5915,19 +5915,21 @@ comment at the start of cc-engine.el for more info."
        (cond
         ((> pos start)                 ; Nothing but literals
          base)
-        ((> base (point-min))
+        ((and
+          (> base (point-min))
+          (> (- base try-size) (point-min))) ; prevent infinite recursion.
          (c-determine-limit how-far-back base (* 2 try-size) org-start))
         (t base)))
        ((>= count how-far-back)
        (c-determine-limit-no-macro
-       (+ (car elt) (- count how-far-back))
-       org-start))
+        (+ (car elt) (- count how-far-back))
+        org-start))
        ((eq base (point-min))
        (point-min))
        ((> base (- start try-size)) ; Can only happen if we hit point-min.
        (c-determine-limit-no-macro
-       (car elt)
-       org-start))
+        (car elt)
+        org-start))
        (t
        (c-determine-limit (- how-far-back count) base (* 2 try-size)
                           org-start))))))
@@ -10146,6 +10148,24 @@ This function might do hidden buffer changes."
        ;; This identifier is bound only in the inner let.
        '(setq start id-start))))
 
+(defmacro c-fdoc-assymetric-space-about-asterisk ()
+  ;; We've got a "*" at `id-start' between two identifiers, the first at
+  ;; `type-start'.  Return non-nil when there is either whitespace between the
+  ;; first id and the "*" or between the "*" and the second id, but not both.
+  `(let ((space-before-id
+        (save-excursion
+          (goto-char id-start)         ; Position of "*".
+          (and (> (skip-chars-forward "* \t\n\r") 0)
+               (memq (char-before) '(?\  ?\t ?\n ?\r)))))
+       (space-after-type
+        (save-excursion
+          (goto-char type-start)
+          (and (c-forward-type nil t)
+               (or (eolp)
+                   (memq (char-after) '(?\  ?\t)))))))
+     (not (eq (not space-before-id)
+             (not space-after-type)))))
+
 (defun c-forward-decl-or-cast-1 (preceding-token-end context last-cast-end
                                                     &optional inside-macro)
   ;; Move forward over a declaration or a cast if at the start of one.
@@ -11166,19 +11186,25 @@ This function might do hidden buffer changes."
               ;; CASE 16
               (when (and got-prefix-before-parens
                          at-type
-                         (or at-decl-end (looking-at "=[^=]"))
                          (memq context '(nil top))
                          (or (not got-suffix)
                              at-decl-start))
                 ;; Got something like "foo * bar;".  Since we're not inside
                 ;; an arglist it would be a meaningless expression because
                 ;; the result isn't used.  We therefore choose to recognize
-                ;; it as a declaration.  We only allow a suffix (which makes
-                ;; the construct look like a function call) when
-                ;; `at-decl-start' provides additional evidence that we do
-                ;; have a declaration.
+                ;; it as a declaration when there's "symmetrical WS" around
+                ;; the "*" or the flag `c-assymetry-fontification-flag' is
+                ;; not set.  We only allow a suffix (which makes the
+                ;; construct look like a function call) when `at-decl-start'
+                ;; provides additional evidence that we do have a
+                ;; declaration.
                 (setq maybe-expression t)
-                (throw 'at-decl-or-cast t))
+                (when (or (not c-asymmetry-fontification-flag)
+                          (looking-at "=[^=]")
+                          (c-fdoc-assymetric-space-about-asterisk))
+                  (when (eq at-type 'maybe)
+                    (setq unsafe-maybe t))
+                  (throw 'at-decl-or-cast t)))
 
               ;; CASE 17
               (when (and (or got-suffix-after-parens
@@ -11197,24 +11223,12 @@ This function might do hidden buffer changes."
                          got-prefix-before-parens
                          at-type
                          (or (not got-suffix)
-                             at-decl-start))
-                (let ((space-before-id
-                       (save-excursion
-                         (goto-char id-start) ; Position of "*".
-                         (and (> (skip-chars-forward "* \t\n\r") 0)
-                              (memq (char-before) '(?\  ?\t ?\n ?\r)))))
-                      (space-after-type
-                       (save-excursion
-                         (goto-char type-start)
-                         (and (c-forward-type nil t)
-                              (or (eolp)
-                                  (memq (char-after) '(?\  ?\t)))))))
-                  (when (not (eq (not space-before-id)
-                                 (not space-after-type)))
-                    (when (eq at-type 'maybe)
-                      (setq unsafe-maybe t))
-                    (setq maybe-expression t)
-                    (throw 'at-decl-or-cast t)))))
+                             at-decl-start)
+                         (c-fdoc-assymetric-space-about-asterisk))
+                (when (eq at-type 'maybe)
+                  (setq unsafe-maybe t))
+                (setq maybe-expression t)
+                (throw 'at-decl-or-cast t)))
 
           ;; CASE 18
           (when (and at-decl-end
diff --git a/lisp/progmodes/dockerfile-ts-mode.el 
b/lisp/progmodes/dockerfile-ts-mode.el
index 23ac48a6117..c9125bc6cbd 100644
--- a/lisp/progmodes/dockerfile-ts-mode.el
+++ b/lisp/progmodes/dockerfile-ts-mode.el
@@ -51,9 +51,27 @@
      ((parent-is "expose_instruction") (nth-sibling 1) 0)
      ((parent-is "label_instruction") (nth-sibling 1) 0)
      ((parent-is "shell_command") first-sibling 0)
-     ((parent-is "string_array") first-sibling 1)))
+     ((parent-is "string_array") first-sibling 1)
+     ((dockerfile-ts-mode--line-continuation-p) 
dockerfile-ts-mode--line-continuation-anchor 0)))
   "Tree-sitter indent rules.")
 
+(defun dockerfile-ts-mode--line-continuation-p ()
+  "Return t if the current node is a line continuation node."
+  (lambda (node _ _ &rest _)
+    (string= (treesit-node-type node) "\n")))
+
+(defun dockerfile-ts-mode--line-continuation-anchor (_ _ &rest _)
+  "This anchor is used to align any nodes that are part of a line
+continuation to the previous entry."
+  (save-excursion
+    (forward-line -1)
+    (let ((prev-node (treesit-node-at (point))))
+      (if (string= (treesit-node-type prev-node) "\\\n")
+          (back-to-indentation)
+        (forward-word)
+        (forward-char))
+      (+ 1 (- (point) (pos-bol))))))
+
 (defvar dockerfile-ts-mode--keywords
   '("ADD" "ARG" "AS" "CMD" "COPY" "CROSS_BUILD" "ENTRYPOINT" "ENV"
     "EXPOSE" "FROM" "HEALTHCHECK" "LABEL" "MAINTAINER" "ONBUILD" "RUN"
diff --git a/lisp/progmodes/go-ts-mode.el b/lisp/progmodes/go-ts-mode.el
index 93a3bcc594b..7dafe9b2e3d 100644
--- a/lisp/progmodes/go-ts-mode.el
+++ b/lisp/progmodes/go-ts-mode.el
@@ -35,6 +35,7 @@
 (declare-function treesit-node-child "treesit.c")
 (declare-function treesit-node-child-by-field-name "treesit.c")
 (declare-function treesit-node-start "treesit.c")
+(declare-function treesit-node-end "treesit.c")
 (declare-function treesit-node-type "treesit.c")
 (declare-function treesit-search-subtree "treesit.c")
 
diff --git a/lisp/progmodes/hideshow.el b/lisp/progmodes/hideshow.el
index c160e6ad1df..b878986d7a4 100644
--- a/lisp/progmodes/hideshow.el
+++ b/lisp/progmodes/hideshow.el
@@ -256,10 +256,14 @@ This has effect only if `search-invisible' is set to 
`open'."
 (defvar hs-special-modes-alist
   (mapcar #'purecopy
   '((c-mode "{" "}" "/[*/]" nil nil)
+    (c-ts-mode "{" "}" "/[*/]" nil nil)
     (c++-mode "{" "}" "/[*/]" nil nil)
+    (c++-ts-mode "{" "}" "/[*/]" nil nil)
     (bibtex-mode ("@\\S(*\\(\\s(\\)" 1))
     (java-mode "{" "}" "/[*/]" nil nil)
+    (java-ts-mode "{" "}" "/[*/]" nil nil)
     (js-mode "{" "}" "/[*/]" nil)
+    (js-ts-mode "{" "}" "/[*/]" nil)
     (mhtml-mode "{\\|<[^/>]*?" "}\\|</[^/>]*[^/]>" "<!--" mhtml-forward nil)
     ;; Add more support here.
     ))
diff --git a/lisp/progmodes/java-ts-mode.el b/lisp/progmodes/java-ts-mode.el
index dbd63698770..e4153725efd 100644
--- a/lisp/progmodes/java-ts-mode.el
+++ b/lisp/progmodes/java-ts-mode.el
@@ -89,6 +89,7 @@
      ((query "(method_declaration (block (_) @indent))") parent-bol 
java-ts-mode-indent-offset)
      ((parent-is "local_variable_declaration") parent-bol 
java-ts-mode-indent-offset)
      ((parent-is "expression_statement") parent-bol java-ts-mode-indent-offset)
+     ((match "type_identifier" "field_declaration") parent-bol 0)
      ((parent-is "field_declaration") parent-bol java-ts-mode-indent-offset)
      ((parent-is "return_statement") parent-bol java-ts-mode-indent-offset)
      ((parent-is "variable_declarator") parent-bol java-ts-mode-indent-offset)
diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el
index dca93c856fc..6ae325c0657 100644
--- a/lisp/progmodes/js.el
+++ b/lisp/progmodes/js.el
@@ -3546,9 +3546,18 @@ This function is intended for use in 
`after-change-functions'."
              (identifier)
              @font-lock-function-name-face)
       value: (array (number) (function)))
+     ;; full module imports
      (import_clause (identifier) @font-lock-variable-name-face)
-     (import_clause (named_imports (import_specifier (identifier))
-                                   @font-lock-variable-name-face)))
+     ;; named imports with aliasing
+     (import_clause (named_imports (import_specifier
+                                    alias: (identifier) 
@font-lock-variable-name-face)))
+     ;; named imports without aliasing
+     (import_clause (named_imports (import_specifier
+                                    !alias
+                                    name: (identifier) 
@font-lock-variable-name-face)))
+
+     ;; full namespace import (* as alias)
+     (import_clause (namespace_import (identifier) 
@font-lock-variable-name-face)))
 
    :language 'javascript
    :feature 'property
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index 59270070484..2343adf4698 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -1,7 +1,7 @@
 ;;; project.el --- Operations on the current project  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
-;; Version: 0.9.5
+;; Version: 0.9.6
 ;; Package-Requires: ((emacs "26.1") (xref "1.4.0"))
 
 ;; This is a GNU ELPA :core package.  Avoid using functionality that
@@ -530,7 +530,10 @@ project backend implementation of 
`project-external-roots'.")
                dir
                (lambda (d)
                  ;; Maybe limit count to 100 when we can drop Emacs < 28.
-                 (setq last-matches (directory-files d nil marker-re t)))))
+                 (setq last-matches
+                       (condition-case nil
+                           (directory-files d nil marker-re t)
+                         (file-missing nil))))))
              (backend
               (cl-find-if
                (lambda (b)
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index a869cdc5fdb..df0d1c96965 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -6715,8 +6715,8 @@ implementations: `python-mode' and `python-ts-mode'."
     (when python-indent-guess-indent-offset
       (python-indent-guess-indent-offset))
 
-    (add-to-list 'auto-mode-alist
-                 '("\\.py[iw]?\\'\\|python[0-9.]*" . python-ts-mode))))
+    (add-to-list 'auto-mode-alist '("\\.py[iw]?\\'" . python-ts-mode))
+    (add-to-list 'interpreter-mode-alist '("python[0-9.]*" . python-ts-mode))))
 
 ;;; Completion predicates for M-x
 ;; Commands that only make sense when editing Python code
diff --git a/lisp/progmodes/ruby-ts-mode.el b/lisp/progmodes/ruby-ts-mode.el
index 1144caf79b6..beaab2e76e6 100644
--- a/lisp/progmodes/ruby-ts-mode.el
+++ b/lisp/progmodes/ruby-ts-mode.el
@@ -209,9 +209,6 @@ values of OVERRIDE"
     (treesit-fontify-with-override (max plus-1 start) (min node-end end)
                                    font-lock-comment-face override)))
 
-(defun ruby-ts--builtin-method-p (node)
-  (string-match-p ruby-ts--builtin-methods (treesit-node-text node t)))
-
 (defun ruby-ts--font-lock-settings (language)
   "Tree-sitter font-lock settings for Ruby."
   (treesit-font-lock-rules
@@ -340,7 +337,7 @@ values of OVERRIDE"
    :language language
    :feature 'builtin-function
    `((((identifier) @font-lock-builtin-face)
-      (:pred ruby-ts--builtin-method-p @font-lock-builtin-face)))
+      (:match ,ruby-ts--builtin-methods @font-lock-builtin-face)))
 
    ;; Yuan recommends also putting method definitions into the
    ;; 'function' category (thus keeping it in both).  I've opted to
@@ -1042,9 +1039,12 @@ leading double colon is not added."
                             "parenthesized_statements"
                             "if"
                             "case"
+                            "when"
                             "block"
                             "do_block"
-                            "begin")))
+                            "begin"
+                            "binary"
+                            "assignment")))
 
   ;; AFAIK, Ruby can not nest methods
   (setq-local treesit-defun-prefer-top-level nil)
diff --git a/lisp/progmodes/rust-ts-mode.el b/lisp/progmodes/rust-ts-mode.el
index 3a6cb61b719..e317793d211 100644
--- a/lisp/progmodes/rust-ts-mode.el
+++ b/lisp/progmodes/rust-ts-mode.el
@@ -37,6 +37,7 @@
 (declare-function treesit-node-child-by-field-name "treesit.c")
 (declare-function treesit-node-start "treesit.c")
 (declare-function treesit-node-type "treesit.c")
+(declare-function treesit-node-parent "treesit.c")
 
 (defcustom rust-ts-mode-indent-offset 4
   "Number of spaces for each indentation step in `rust-ts-mode'."
@@ -275,6 +276,28 @@ Return nil if there is no name or if NODE is not a defun 
node."
      (treesit-node-text
       (treesit-node-child-by-field-name node "name") t))))
 
+(defun rust-ts-mode--syntax-propertize (beg end)
+  "Apply syntax text property to template delimiters between BEG and END.
+
+< and > are usually punctuation, e.g., as greater/less-than.  But
+when used for types, they should be considered pairs.
+
+This function checks for < and > in the changed RANGES and apply
+appropriate text property to alter the syntax of template
+delimiters < and >'s."
+  (goto-char beg)
+  (while (re-search-forward (rx (or "<" ">")) end t)
+    (pcase (treesit-node-type
+            (treesit-node-parent
+             (treesit-node-at (match-beginning 0))))
+      ("type_arguments"
+       (put-text-property (match-beginning 0)
+                          (match-end 0)
+                          'syntax-table
+                          (pcase (char-before)
+                            (?< '(4 . ?>))
+                            (?> '(5 . ?<))))))))
+
 ;;;###autoload
 (define-derived-mode rust-ts-mode prog-mode "Rust"
   "Major mode for editing Rust, powered by tree-sitter."
@@ -284,6 +307,10 @@ Return nil if there is no name or if NODE is not a defun 
node."
   (when (treesit-ready-p 'rust)
     (treesit-parser-create 'rust)
 
+    ;; Syntax.
+    (setq-local syntax-propertize-function
+                #'rust-ts-mode--syntax-propertize)
+
     ;; Comments.
     (c-ts-common-comment-setup)
 
diff --git a/lisp/progmodes/typescript-ts-mode.el 
b/lisp/progmodes/typescript-ts-mode.el
index 9c4f49efd5e..3437ea43505 100644
--- a/lisp/progmodes/typescript-ts-mode.el
+++ b/lisp/progmodes/typescript-ts-mode.el
@@ -196,8 +196,18 @@ Argument LANGUAGE is either `typescript' or `tsx'."
      (catch_clause
       parameter: (identifier) @font-lock-variable-name-face)
 
+     ;; full module imports
      (import_clause (identifier) @font-lock-variable-name-face)
-     (import_clause (named_imports (import_specifier (identifier)) 
@font-lock-variable-name-face)))
+     ;; named imports with aliasing
+     (import_clause (named_imports (import_specifier
+                                    alias: (identifier) 
@font-lock-variable-name-face)))
+     ;; named imports without aliasing
+     (import_clause (named_imports (import_specifier
+                                    !alias
+                                    name: (identifier) 
@font-lock-variable-name-face)))
+
+     ;; full namespace import (* as alias)
+     (import_clause (namespace_import (identifier) 
@font-lock-variable-name-face)))
 
    :language language
    :feature 'identifier
diff --git a/lisp/repeat.el b/lisp/repeat.el
index 0124ff4bc0c..37d4aaec985 100644
--- a/lisp/repeat.el
+++ b/lisp/repeat.el
@@ -349,7 +349,7 @@ For example, you can set it to <return> like 
`isearch-exit'."
   :version "28.1")
 
 (defcustom repeat-exit-timeout nil
-  "Break the repetition chain of keys after specified timeout.
+  "Break the repetition chain of keys after specified amount of idle time.
 When a number, exit the transient repeating mode after idle time
 of the specified number of seconds.
 You can also set the property `repeat-exit-timeout' on the command symbol.
@@ -380,12 +380,12 @@ This property can override the value of this variable."
 
 (defcustom repeat-check-key t
   "Whether to check that the last key exists in the repeat map.
-When non-nil and the last typed key (with or without modifiers)
-doesn't exist in the keymap attached by the `repeat-map' property,
-then don't activate that keymap for the next command.  So only the
-same keys among repeatable keys are allowed in the repeating sequence.
-For example, with a non-nil value, only \\`C-x u u' repeats undo,
-whereas \\`C-/ u' doesn't.
+When non-nil, and the last typed key (with or without modifiers)
+doesn't exist in the keymap specified by the `repeat-map' property
+of the command, don't activate that keymap for the next command.
+Thus, when this is non-nil, only the same keys among repeatable
+keys are allowed in the repeating sequence. For example, with a
+non-nil value, only \\`C-x u u' repeats undo, whereas \\`C-/ u' doesn't.
 
 You can also set the property `repeat-check-key' on the command symbol.
 This property can override the value of this variable.
@@ -398,7 +398,7 @@ but the property value is `t', then check the last key."
 
 (defcustom repeat-echo-function #'repeat-echo-message
   "Function to display a hint about available keys.
-Function is called after every repeatable command with one argument:
+The function is called after every repeatable command with one argument:
 a repeating map, or nil after deactivating the transient repeating mode.
 You can use `add-function' for multiple functions simultaneously."
   :type '(choice (const :tag "Show hints in the echo area"
@@ -422,8 +422,12 @@ the map can't be set on the command symbol property 
`repeat-map'.")
 ;;;###autoload
 (define-minor-mode repeat-mode
   "Toggle Repeat mode.
-When Repeat mode is enabled, and the command symbol has the property named
-`repeat-map', this map is activated temporarily for the next command.
+When Repeat mode is enabled, certain commands bound to multi-key
+sequences can be repeated by typing a single key, after typing the
+full key sequence once.
+The commands which can be repeated like that are those whose symbol
+ has the property `repeat-map' which specifies a keymap of single
+keys for repeating.
 See `describe-repeat-maps' for a list of all repeatable commands."
   :global t :group 'repeat
   (if (not repeat-mode)
@@ -459,7 +463,7 @@ See `describe-repeat-maps' for a list of all repeatable 
commands."
         rep-map))))
 
 (defun repeat-check-key (key map)
-  "Check if the last key is suitable to activate the repeating MAP."
+  "Check if the last KEY is suitable for activating the repeating MAP."
   (let* ((prop (repeat--command-property 'repeat-check-key))
          (check-key (unless (eq prop 'no) (or prop repeat-check-key))))
     (or (not check-key)
@@ -471,7 +475,7 @@ See `describe-repeat-maps' for a list of all repeatable 
commands."
   "Previous minibuffer state.")
 
 (defun repeat-check-map (map)
-  "Decides whether MAP can be used for the next command."
+  "Decide whether MAP can be used for the next command."
   (and map
        ;; Detect changes in the minibuffer state to allow repetitions
        ;; in the same minibuffer, but not when the minibuffer is activated
@@ -547,7 +551,7 @@ This function can be used to force exit of repetition while 
it's active."
     (setq repeat-exit-function nil)))
 
 (defun repeat-echo-message-string (keymap)
-  "Return a string with a list of repeating keys."
+  "Return a string with the list of repeating keys in KEYMAP."
   (let (keys)
     (map-keymap (lambda (key cmd) (and cmd (push key keys))) keymap)
     (format-message "Repeat with %s%s"
@@ -565,7 +569,8 @@ This function can be used to force exit of repetition while 
it's active."
                       ""))))
 
 (defun repeat-echo-message (keymap)
-  "Display available repeating keys in the echo area."
+  "Display in the echo area the repeating keys defined by KEYMAP.
+See `repeat-echo-function' to enable/disable."
   (let ((message-log-max nil))
     (if keymap
         (let ((message (repeat-echo-message-string keymap)))
@@ -586,7 +591,9 @@ This function can be used to force exit of repetition while 
it's active."
   "String displayed in the mode line in repeating mode.")
 
 (defun repeat-echo-mode-line (keymap)
-  "Display the repeat indicator in the mode line."
+  "Display the repeat indicator in the mode line.
+KEYMAP should be non-nil, but is otherwise ignored.
+See `repeat-echo-function' to enable/disable."
   (if keymap
       (unless (assq 'repeat-in-progress mode-line-modes)
         (add-to-list 'mode-line-modes (list 'repeat-in-progress
@@ -596,8 +603,11 @@ This function can be used to force exit of repetition 
while it's active."
 (declare-function help-fns--analyze-function "help-fns" (function))
 
 (defun describe-repeat-maps ()
-  "Describe mappings of commands repeatable by symbol property `repeat-map'.
-Used in `repeat-mode'."
+  "Describe transient keymaps installed for repeating multi-key commands.
+These keymaps enable repetition of commands bound to multi-key
+sequences by typing just one key, when `repeat-mode' is enabled.
+Commands that can be repeated this way must have their symbol
+to have the `repeat-map' property whose value specified a keymap."
   (interactive)
   (require 'help-fns)
   (let ((help-buffer-under-preparation t))
@@ -612,7 +622,9 @@ Used in `repeat-mode'."
       (with-help-window (help-buffer)
         (with-current-buffer standard-output
           (setq-local outline-regexp "[*]+")
-          (insert "A list of keymaps used by commands with the symbol property 
`repeat-map'.\n")
+          (insert "\
+A list of keymaps and their single-key shortcuts for repeating commands.
+Click on a keymap to see the commands repeatable by the keymap.\n")
 
           (dolist (keymap (sort keymaps (lambda (a b)
                                           (when (and (symbolp (car a))
diff --git a/lisp/simple.el b/lisp/simple.el
index 561c7b568ab..bed6dfb8292 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -2738,7 +2738,8 @@ instead."
   nil)
 
 (cl-defmethod oclosure-interactive-form ((f cconv--interactive-helper))
-  `(interactive (funcall ',(cconv--interactive-helper--if f))))
+  (let ((if (cconv--interactive-helper--if f)))
+    `(interactive ,(if (functionp if) `(funcall ',if) if))))
 
 (defun command-execute (cmd &optional record-flag keys special)
   ;; BEWARE: Called directly from the C code.
@@ -4554,6 +4555,9 @@ If the output is short enough to display in the echo area
 \(determined by the variable `max-mini-window-height' if
 `resize-mini-windows' is non-nil), it is shown there.
 Otherwise, the buffer containing the output is displayed.
+Note that if `shell-command-dont-erase-buffer' is non-nil,
+the echo area could display more than just the output of the
+last command.
 
 If there is output and an error, and you did not specify \"insert it
 in the current buffer\", a message about the error goes at the end
@@ -4848,6 +4852,9 @@ If the output is short enough to display in the echo area
 `resize-mini-windows' is non-nil), it is shown there.
 Otherwise it is displayed in the buffer named by `shell-command-buffer-name'.
 The output is available in that buffer in both cases.
+Note that if `shell-command-dont-erase-buffer' is non-nil,
+the echo area could display more than just the output of the
+last command.
 
 If there is output and an error, a message about the error
 appears at the end of the output.
@@ -5865,6 +5872,25 @@ The value 0 disables blinking."
   :group 'killing
   :version "28.1")
 
+(defcustom copy-region-blink-predicate #'region-indistinguishable-p
+  "Whether the cursor must be blinked after a copy.
+When this condition holds, and the copied region fits in the
+current window, `kill-ring-save' will blink the cursor between
+point and mark for `copy-region-blink-delay' seconds."
+  :type '(radio (function-item region-indistinguishable-p)
+                (function-item :doc "Always blink point and mark." always)
+                (function-item :doc "Never blink point and mark." ignore)
+                (function :tag "Other predicate function"))
+  :group 'killing
+  :version "29.1")
+
+(defun region-indistinguishable-p ()
+  "Whether the current region is not denoted visually.
+This holds when the region is inactive, or when the `region' face
+cannot be distinguished from the `default' face."
+  (not (and (region-active-p)
+            (face-differs-from-default-p 'region))))
+
 (defun indicate-copied-region (&optional message-len)
   "Indicate that the region text has been copied interactively.
 If the mark is visible in the selected window, blink the cursor between
@@ -5885,8 +5911,7 @@ of this sample text; it defaults to 40."
        ;; was selected.  Don't do it if the region is highlighted.
        (when (and (numberp copy-region-blink-delay)
                   (> copy-region-blink-delay 0)
-                  (or (not (region-active-p))
-                      (not (face-background 'region nil t))))
+                  (funcall copy-region-blink-predicate))
          ;; Swap point and mark.
          (set-marker (mark-marker) (point) (current-buffer))
          (goto-char mark)
diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index 9f53b649efd..7c3069ca269 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -2653,14 +2653,14 @@ When `switch-to-buffer-obey-display-actions' is non-nil,
 (keymap-set tab-prefix-map "t"   #'other-tab-prefix)
 
 (defvar-keymap tab-bar-switch-repeat-map
-  :doc "Keymap to repeat tab switch key sequences \\`C-x t o o O'.
+  :doc "Keymap to repeat tab switch commands `tab-next' and `tab-previous'.
 Used in `repeat-mode'."
   :repeat t
   "o" #'tab-next
   "O" #'tab-previous)
 
 (defvar-keymap tab-bar-move-repeat-map
-  :doc "Keymap to repeat tab move key sequences \\`C-x t m m M'.
+  :doc "Keymap to repeat tab move commands `tab-move' and 
`tab-bar-move-tab-backward'.
 Used in `repeat-mode'."
   :repeat t
   "m" #'tab-move
diff --git a/lisp/transient.el b/lisp/transient.el
index 42268aedab7..0b41bc44adb 100644
--- a/lisp/transient.el
+++ b/lisp/transient.el
@@ -798,8 +798,8 @@ They become the value of this argument.")
 (defclass transient-columns (transient-group) ()
   "Group class that displays elements organized in columns.
 Direct elements have to be groups whose elements have to be
-commands or string.  Each subgroup represents a column.  This
-class takes care of inserting the subgroups' elements.")
+commands or strings.  Each subgroup represents a column.
+This class takes care of inserting the subgroups' elements.")
 
 (defclass transient-subgroups (transient-group) ()
   "Group class that wraps other groups.
@@ -860,7 +860,7 @@ to the setup function:
            (indent defun)
            (doc-string 3))
   (pcase-let ((`(,class ,slots ,suffixes ,docstr ,body)
-               (transient--expand-define-args args)))
+               (transient--expand-define-args args arglist)))
     `(progn
        (defalias ',name
          ,(if body
@@ -913,7 +913,7 @@ ARGLIST.  The infix arguments are usually accessed by using
            (indent defun)
            (doc-string 3))
   (pcase-let ((`(,class ,slots ,_ ,docstr ,body)
-               (transient--expand-define-args args)))
+               (transient--expand-define-args args arglist)))
     `(progn
        (defalias ',name (lambda ,arglist ,@body))
        (put ',name 'interactive-only t)
@@ -921,7 +921,7 @@ ARGLIST.  The infix arguments are usually accessed by using
        (put ',name 'transient--suffix
             (,(or class 'transient-suffix) :command ',name ,@slots)))))
 
-(defmacro transient-define-infix (name _arglist &rest args)
+(defmacro transient-define-infix (name arglist &rest args)
   "Define NAME as a transient infix command.
 
 ARGLIST is always ignored and reserved for future use.
@@ -962,7 +962,7 @@ keyword.
            (indent defun)
            (doc-string 3))
   (pcase-let ((`(,class ,slots ,_ ,docstr ,_)
-               (transient--expand-define-args args)))
+               (transient--expand-define-args args arglist)))
     `(progn
        (defalias ',name ,(transient--default-infix-command))
        (put ',name 'interactive-only t)
@@ -980,7 +980,9 @@ example, sets a variable use `transient-define-infix' 
instead.
 
 \(fn NAME ARGLIST [DOCSTRING] [KEYWORD VALUE]...)")
 
-(defun transient--expand-define-args (args)
+(defun transient--expand-define-args (args &optional arglist)
+  (unless (listp arglist)
+    (error "Mandatory ARGLIST is missing"))
   (let (class keys suffixes docstr)
     (when (stringp (car args))
       (setq docstr (pop args)))
@@ -1150,7 +1152,7 @@ example, sets a variable use `transient-define-infix' 
instead.
 PREFIX is a prefix command, a symbol.
 SUFFIX is a suffix command or a group specification (of
   the same forms as expected by `transient-define-prefix').
-Intended for use in PREFIX's `:setup-children' function."
+Intended for use in a group's `:setup-children' function."
   (eval (car (transient--parse-child prefix suffix))))
 
 (defun transient-parse-suffixes (prefix suffixes)
@@ -1158,7 +1160,7 @@ Intended for use in PREFIX's `:setup-children' function."
 PREFIX is a prefix command, a symbol.
 SUFFIXES is a list of suffix command or a group specification
   (of the same forms as expected by `transient-define-prefix').
-Intended for use in PREFIX's `:setup-children' function."
+Intended for use in a group's `:setup-children' function."
   (mapcar (apply-partially #'transient-parse-suffix prefix) suffixes))
 
 ;;; Edit
@@ -1469,14 +1471,24 @@ probably use this instead:
     (cl-check-type command command))
   (if (or transient--prefix
           transient-current-prefix)
-      (cl-find-if (lambda (obj)
-                    (eq (transient--suffix-command obj)
+      (let ((suffixes
+             (cl-remove-if-not
+              (lambda (obj)
+                (eq (transient--suffix-command obj)
+                    (or command
                         ;; When `this-command' is `transient-set-level',
                         ;; its reader needs to know what command is being
                         ;; configured.
-                        (or command this-original-command)))
-                  (or transient--suffixes
-                      transient-current-suffixes))
+                        this-original-command)))
+              (or transient--suffixes
+                  transient-current-suffixes))))
+        (or (and (cdr suffixes)
+                 (cl-find-if
+                  (lambda (obj)
+                    (equal (listify-key-sequence (transient--kbd (oref obj 
key)))
+                           (listify-key-sequence (this-command-keys))))
+                  suffixes))
+            (car suffixes)))
     (when-let* ((obj (get (or command this-command) 'transient--suffix))
                 (obj (clone obj)))
       ;; Cannot use and-let* because of debbugs#31840.
diff --git a/lisp/treesit.el b/lisp/treesit.el
index 29b29d2665a..d11e57fef8a 100644
--- a/lisp/treesit.el
+++ b/lisp/treesit.el
@@ -87,6 +87,7 @@
 (declare-function treesit-search-subtree "treesit.c")
 (declare-function treesit-search-forward "treesit.c")
 (declare-function treesit-induce-sparse-tree "treesit.c")
+(declare-function treesit-subtree-stat "treesit.c")
 
 (declare-function treesit-available-p "treesit.c")
 
@@ -554,7 +555,27 @@ omitted, default END to BEG."
               "Generic tree-sitter font-lock error"
               'treesit-error)
 
-(defvar-local treesit-font-lock-level 3
+(defun treesit--font-lock-level-setter (sym val)
+  "Custom setter for `treesit-font-lock-level'."
+  (set-default sym val)
+  (and (treesit-available-p)
+       (named-let loop ((res nil)
+                        (buffers (buffer-list)))
+         (if (null buffers)
+             (mapc (lambda (b)
+                     (with-current-buffer b
+                       (setq-local treesit-font-lock-level val)
+                       (treesit-font-lock-recompute-features)
+                       (treesit-font-lock-fontify-region (point-min)
+                                                         (point-max))))
+                   res)
+           (let ((buffer (car buffers)))
+             (with-current-buffer buffer
+               (if (treesit-parser-list)
+                   (loop (append res (list buffer)) (cdr buffers))
+                 (loop res (cdr buffers)))))))))
+
+(defcustom treesit-font-lock-level 3
   "Decoration level to be used by tree-sitter fontifications.
 
 Major modes categorize their fontification features into levels,
@@ -562,16 +583,24 @@ from 1 which is the absolute minimum, to 4 that yields 
the maximum
 fontifications.
 
 Level 1 usually contains only comments and definitions.
-Level 2 usually adds keywords, strings, constants, types, etc.
-Level 3 usually represents a full-blown fontification, including
-assignment, constants, numbers, properties, etc.
+Level 2 usually adds keywords, strings, data types, etc.
+Level 3 usually represents full-blown fontifications, including
+assignments, constants, numbers and literals, properties, etc.
 Level 4 adds everything else that can be fontified: delimiters,
-operators, brackets, all functions and variables, etc.
+operators, brackets, punctuation, all functions and variables, etc.
 
 In addition to the decoration level, individual features can be
 turned on/off by calling `treesit-font-lock-recompute-features'.
 Changing the decoration level requires calling
-`treesit-font-lock-recompute-features' to have an effect.")
+`treesit-font-lock-recompute-features' to have an effect, unless
+done via `customize-variable'.
+
+To see which syntactical categories are fontified by each level
+in a particular major mode, examine the buffer-local value of the
+variable `treesit-font-lock-feature-list'."
+  :type 'integer
+  :set #'treesit--font-lock-level-setter
+  :version "29.1")
 
 (defvar-local treesit--font-lock-query-expand-range (cons 0 0)
   "The amount to expand the start and end of the region when fontifying.
@@ -892,27 +921,20 @@ LIMIT is the recursion limit, which defaults to 100."
             (push r result))
         (push child result))
       (setq child (treesit-node-next-sibling child)))
-    ;; If NODE has no child, keep NODE.
-    (or result (list node))))
+    ;; If NODE has no child, keep NODE.  If LIMIT is exceeded, return
+    ;; nil.
+    (or result (and (> limit 0) (list node)))))
 
 (defsubst treesit--node-length (node)
   "Return the length of the text of NODE."
   (- (treesit-node-end node) (treesit-node-start node)))
 
-(defvar-local treesit--font-lock-fast-mode nil
+(defvar-local treesit--font-lock-fast-mode 'unspecified
   "If this variable is t, change the way we query so it's faster.
 This is not a general optimization and should be RARELY needed!
 See comments in `treesit-font-lock-fontify-region' for more
 detail.")
 
-(defvar-local treesit--font-lock-fast-mode-grace-count 5
-  "Grace counts before we turn on the fast mode.
-
-When query takes abnormally long time to execute, we turn on the
-\"fast mode\", but just to be on the safe side, we only turn on
-the fast mode after this number of offenses.  See bug#60691,
-bug#60223.")
-
 ;; Some details worth explaining:
 ;;
 ;; 1. When we apply face to a node, we clip the face into the
@@ -964,36 +986,34 @@ If LOUDLY is non-nil, display some debugging information."
            (enable (nth 1 setting))
            (override (nth 3 setting))
            (language (treesit-query-language query)))
-      (when-let ((nodes (list (treesit-buffer-root-node language)))
-                 ;; Only activate if ENABLE flag is t.
-                 (activate (eq t enable)))
-        (ignore activate)
 
-        ;; If we run into problematic files, use the "fast mode" to
-        ;; try to recover.  See comment #2 above for more explanation.
-        (when treesit--font-lock-fast-mode
-          (setq nodes (treesit--children-covering-range-recurse
-                       (car nodes) start end (* 4 jit-lock-chunk-size))))
+      ;; Use deterministic way to decide whether to turn on "fast
+      ;; mode". (See bug#60691, bug#60223.)
+      (when (eq treesit--font-lock-fast-mode 'unspecified)
+        (pcase-let ((`(,max-depth ,max-width)
+                     (treesit-subtree-stat
+                      (treesit-buffer-root-node language))))
+          (if (or (> max-depth 100) (> max-width 4000))
+              (setq treesit--font-lock-fast-mode t)
+            (setq treesit--font-lock-fast-mode nil))))
+
+      (when-let* ((root (treesit-buffer-root-node language))
+                  (nodes (if (eq t treesit--font-lock-fast-mode)
+                             (treesit--children-covering-range-recurse
+                              root start end (* 4 jit-lock-chunk-size))
+                           (list (treesit-buffer-root-node language))))
+                  ;; Only activate if ENABLE flag is t.
+                  (activate (eq t enable)))
+        (ignore activate)
 
         ;; Query each node.
         (dolist (sub-node nodes)
           (let* ((delta-start (car treesit--font-lock-query-expand-range))
                  (delta-end (cdr treesit--font-lock-query-expand-range))
-                 (start-time (current-time))
                  (captures (treesit-query-capture
                             sub-node query
                             (max (- start delta-start) (point-min))
-                            (min (+ end delta-end) (point-max))))
-                 (end-time (current-time)))
-            ;; If for any query the query time is strangely long,
-            ;; switch to fast mode (see comments above).
-            (when (and (null treesit--font-lock-fast-mode)
-                       (> (time-to-seconds
-                           (time-subtract end-time start-time))
-                          0.01))
-              (if (> treesit--font-lock-fast-mode-grace-count 0)
-                  (cl-decf treesit--font-lock-fast-mode-grace-count)
-                (setq-local treesit--font-lock-fast-mode t)))
+                            (min (+ end delta-end) (point-max)))))
 
             ;; For each captured node, fontify that node.
             (with-silent-modifications
@@ -1002,12 +1022,14 @@ If LOUDLY is non-nil, display some debugging 
information."
                        (node (cdr capture))
                        (node-start (treesit-node-start node))
                        (node-end (treesit-node-end node)))
+
                   ;; If node is not in the region, take them out.  See
                   ;; comment #3 above for more detail.
                   (if (and (facep face)
                            (or (>= start node-end) (>= node-start end)))
                       (when (or loudly treesit--font-lock-verbose)
                         (message "Captured node %s(%s-%s) but it is outside of 
fontifing region" node node-start node-end))
+
                     (cond
                      ((facep face)
                       (treesit-fontify-with-override
@@ -1015,6 +1037,7 @@ If LOUDLY is non-nil, display some debugging information."
                        face override))
                      ((functionp face)
                       (funcall face node override start end)))
+
                     ;; Don't raise an error if FACE is neither a face nor
                     ;; a function.  This is to allow intermediate capture
                     ;; names used for #match and #eq.
@@ -3033,10 +3056,10 @@ function signals an error."
    :no-value (treesit-parser-set-included-ranges parser '((1 . 4) (5 . 8))))
   (treesit-parser-included-ranges
    :no-eval (treesit-parser-included-ranges parser)
-   :eg-result '((1 . 4) (5 . 8)))
+   :eg-result ((1 . 4) (5 . 8)))
   (treesit-query-range
    :no-eval (treesit-query-range node '((script_element) @cap))
-   :eg-result-string '((1 . 4) (5 . 8)))
+   :eg-result ((1 . 4) (5 . 8)))
 
 
   "Retrieving a node"
@@ -3182,7 +3205,12 @@ function signals an error."
    :eg-result-string "#<treesit-node (translation_unit) in 1-11>")
   (treesit-query-string
    :no-eval (treesit-query-string "int c = 0;" '((identifier) @id) 'c)
-   :eg-result-string "((id . #<treesit-node (identifier) in 5-6>))"))
+   :eg-result-string "((id . #<treesit-node (identifier) in 5-6>))")
+
+  "Misc"
+  (treesit-subtree-stat
+   :no-eval (treesit-subtree-stat node)
+   :eg-result (6 33 487)))
 
 (provide 'treesit)
 
diff --git a/lisp/window.el b/lisp/window.el
index 0cd30822ff6..2d9f746d8fb 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -10567,8 +10567,7 @@ displaying that processes's buffer."
 (define-key ctl-x-4-map "4" 'other-window-prefix)
 
 (defvar-keymap other-window-repeat-map
-  :doc "Keymap to repeat `other-window' key sequences.
-Used in `repeat-mode'."
+  :doc "Keymap to repeat `other-window'.  Used in `repeat-mode'."
   :repeat t
   "o" #'other-window
   "O" (lambda ()
@@ -10578,6 +10577,8 @@ Used in `repeat-mode'."
 
 (defvar-keymap resize-window-repeat-map
   :doc "Keymap to repeat window resizing commands.
+Repeatable commands are `enlarge-window' and `shrink-window',
+and also `enlarge-window-horizontally' and `shrink-window-horizontally'.
 Used in `repeat-mode'."
   :repeat t
   ;; Standard keys:
diff --git a/m4/canonicalize.m4 b/m4/canonicalize.m4
index 03cb0aec93f..d319645fd3f 100644
--- a/m4/canonicalize.m4
+++ b/m4/canonicalize.m4
@@ -1,4 +1,4 @@
-# canonicalize.m4 serial 37
+# canonicalize.m4 serial 38
 
 dnl Copyright (C) 2003-2007, 2009-2023 Free Software Foundation, Inc.
 
@@ -12,7 +12,8 @@ AC_DEFUN([gl_FUNC_CANONICALIZE_FILENAME_MODE],
 [
   AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
   AC_REQUIRE([gl_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK])
-  AC_CHECK_FUNCS_ONCE([canonicalize_file_name faccessat])
+  AC_CHECK_FUNCS_ONCE([canonicalize_file_name])
+  gl_CHECK_FUNCS_ANDROID([faccessat], [[#include <unistd.h>]])
   AC_REQUIRE([gl_DOUBLE_SLASH_ROOT])
   AC_REQUIRE([gl_FUNC_REALPATH_WORKS])
   if test $ac_cv_func_canonicalize_file_name = no; then
@@ -58,7 +59,8 @@ AC_DEFUN([gl_CANONICALIZE_LGPL_SEPARATE],
 [
   AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
   AC_REQUIRE([gl_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK])
-  AC_CHECK_FUNCS_ONCE([canonicalize_file_name faccessat])
+  AC_CHECK_FUNCS_ONCE([canonicalize_file_name])
+  gl_CHECK_FUNCS_ANDROID([faccessat], [[#include <unistd.h>]])
 
   dnl On native Windows, we use _getcwd(), regardless whether getcwd() is
   dnl available through the linker option '-loldnames'.
diff --git a/m4/euidaccess.m4 b/m4/euidaccess.m4
index f0eb5bde84a..7429779c152 100644
--- a/m4/euidaccess.m4
+++ b/m4/euidaccess.m4
@@ -1,4 +1,4 @@
-# euidaccess.m4 serial 16
+# euidaccess.m4 serial 17
 dnl Copyright (C) 2002-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -32,7 +32,7 @@ AC_DEFUN([gl_FUNC_EUIDACCESS],
 # Prerequisites of lib/euidaccess.c.
 AC_DEFUN([gl_PREREQ_EUIDACCESS], [
   dnl Prefer POSIX faccessat over non-standard euidaccess.
-  AC_CHECK_FUNCS_ONCE([faccessat])
+  gl_CHECK_FUNCS_ANDROID([faccessat], [[#include <unistd.h>]])
   dnl Try various other non-standard fallbacks.
   AC_CHECK_HEADERS([libgen.h])
   AC_FUNC_GETGROUPS
diff --git a/m4/faccessat.m4 b/m4/faccessat.m4
index 934c1f41546..a858bfee33d 100644
--- a/m4/faccessat.m4
+++ b/m4/faccessat.m4
@@ -1,4 +1,4 @@
-# serial 10
+# serial 12
 # See if we need to provide faccessat replacement.
 
 dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
@@ -16,9 +16,12 @@ AC_DEFUN([gl_FUNC_FACCESSAT],
   dnl Persuade glibc <unistd.h> to declare faccessat().
   AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
 
-  AC_CHECK_FUNCS_ONCE([faccessat])
+  gl_CHECK_FUNCS_ANDROID([faccessat], [[#include <unistd.h>]])
   if test $ac_cv_func_faccessat = no; then
     HAVE_FACCESSAT=0
+    case "$gl_cv_onwards_func_faccessat" in
+      future*) REPLACE_FACCESSAT=1 ;;
+    esac
   else
     case $gl_cv_func_lstat_dereferences_slashed_symlink in
       *yes) ;;
diff --git a/m4/fchmodat.m4 b/m4/fchmodat.m4
index 7a3ee863e3c..5356da40bae 100644
--- a/m4/fchmodat.m4
+++ b/m4/fchmodat.m4
@@ -1,4 +1,4 @@
-# fchmodat.m4 serial 7
+# fchmodat.m4 serial 8
 dnl Copyright (C) 2004-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -97,6 +97,6 @@ AC_DEFUN([gl_FUNC_FCHMODAT],
 # Prerequisites of lib/fchmodat.c.
 AC_DEFUN([gl_PREREQ_FCHMODAT],
 [
-  AC_CHECK_FUNCS_ONCE([readlinkat])
+  gl_CHECK_FUNCS_ANDROID([readlinkat], [[#include <unistd.h>]])
   :
 ])
diff --git a/m4/futimens.m4 b/m4/futimens.m4
index 3aaa10a0b52..dc0b21b9d51 100644
--- a/m4/futimens.m4
+++ b/m4/futimens.m4
@@ -1,4 +1,4 @@
-# serial 9
+# serial 11
 # See if we need to provide futimens replacement.
 
 dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
@@ -13,9 +13,12 @@ AC_DEFUN([gl_FUNC_FUTIMENS],
   AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS])
   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
   AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
-  AC_CHECK_FUNCS_ONCE([futimens])
+  gl_CHECK_FUNCS_ANDROID([futimens], [[#include <sys/stat.h>]])
   if test $ac_cv_func_futimens = no; then
     HAVE_FUTIMENS=0
+    case "$gl_cv_onwards_func_futimens" in
+      future*) REPLACE_FUTIMENS=1 ;;
+    esac
   else
     AC_CACHE_CHECK([whether futimens works],
       [gl_cv_func_futimens_works],
diff --git a/m4/getloadavg.m4 b/m4/getloadavg.m4
index 79e420baae8..ee83b32f1e0 100644
--- a/m4/getloadavg.m4
+++ b/m4/getloadavg.m4
@@ -7,7 +7,7 @@
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-#serial 10
+#serial 12
 
 # Autoconf defines AC_FUNC_GETLOADAVG, but that is obsolescent.
 # New applications should use gl_GETLOADAVG instead.
@@ -25,8 +25,13 @@ gl_save_LIBS=$LIBS
 # getloadavg is present in libc on glibc >= 2.2, Mac OS X, FreeBSD >= 2.0,
 # NetBSD >= 0.9, OpenBSD >= 2.0, Solaris >= 7.
 HAVE_GETLOADAVG=1
-AC_CHECK_FUNC([getloadavg], [],
-  [gl_func_getloadavg_done=no
+gl_CHECK_FUNCS_ANDROID([getloadavg], [[#include <stdlib.h>]])
+if test $ac_cv_func_getloadavg != yes; then
+   case "$gl_cv_onwards_func_getloadavg" in
+     future*) REPLACE_GETLOADAVG=1 ;;
+   esac
+
+   gl_func_getloadavg_done=no
 
    # Some systems with -lutil have (and need) -lkvm as well, some do not.
    # On Solaris, -lkvm requires nlist from -lelf, so check that first
@@ -73,7 +78,8 @@ AC_CHECK_FUNC([getloadavg], [],
           AC_DEFINE([DGUX], [1], [Define to 1 for DGUX with 
<sys/dg_sys_info.h>.])
           AC_CHECK_LIB([dgc], [dg_sys_info])])
      fi
-   fi])
+   fi
+fi
 
 if test "x$gl_save_LIBS" = x; then
   GETLOADAVG_LIBS=$LIBS
diff --git a/m4/getrandom.m4 b/m4/getrandom.m4
index c508f1a55c3..7b7f9ce2ee8 100644
--- a/m4/getrandom.m4
+++ b/m4/getrandom.m4
@@ -1,4 +1,4 @@
-# getrandom.m4 serial 10
+# getrandom.m4 serial 11
 dnl Copyright 2020-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -18,6 +18,9 @@ AC_DEFUN([gl_FUNC_GETRANDOM],
     ]])
   if test "$ac_cv_func_getrandom" != yes; then
     HAVE_GETRANDOM=0
+    case "$gl_cv_onwards_func_getrandom" in
+      future*) REPLACE_GETRANDOM=1 ;;
+    esac
   else
     dnl On Solaris 11.4 the return type is 'int', not 'ssize_t'.
     AC_CACHE_CHECK([whether getrandom is compatible with its GNU+BSD 
signature],
diff --git a/m4/gettime.m4 b/m4/gettime.m4
index 7e353fcd00e..ec1f97ee0d5 100644
--- a/m4/gettime.m4
+++ b/m4/gettime.m4
@@ -1,4 +1,4 @@
-# gettime.m4 serial 13
+# gettime.m4 serial 14
 dnl Copyright (C) 2002, 2004-2006, 2009-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -18,9 +18,11 @@ AC_DEFUN([gl_GETTIME],
 ])
 
 dnl Tests whether the function timespec_get exists.
-dnl Sets gl_cv_func_timespec_get.
+dnl Sets gl_cv_func_timespec_get and gl_cv_onwards_func_timespec_get.
 AC_DEFUN([gl_CHECK_FUNC_TIMESPEC_GET],
 [
+  AC_REQUIRE([AC_CANONICAL_HOST])
+
   dnl Persuade OpenBSD <time.h> to declare timespec_get().
   AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
 
@@ -29,21 +31,32 @@ AC_DEFUN([gl_CHECK_FUNC_TIMESPEC_GET],
   dnl But at the same time, we need to notice a missing declaration, like
   dnl gl_CHECK_FUNCS_ANDROID does.
   AC_CHECK_DECL([timespec_get], , , [[#include <time.h>]])
-  if test $ac_cv_have_decl_timespec_get = yes; then
-    AC_CACHE_CHECK([for timespec_get], [gl_cv_func_timespec_get],
-      [AC_LINK_IFELSE(
+  AC_CACHE_CHECK([for timespec_get], [gl_cv_onwards_func_timespec_get],
+    [if test $ac_cv_have_decl_timespec_get = yes; then
+       AC_LINK_IFELSE(
          [AC_LANG_PROGRAM(
             [[#include <time.h>
               struct timespec ts;
             ]],
             [[return timespec_get (&ts, 0);]])
          ],
-         [gl_cv_func_timespec_get=yes],
-         [gl_cv_func_timespec_get=no])
-      ])
-  else
-    gl_cv_func_timespec_get=no
-  fi
+         [gl_cv_onwards_func_timespec_get=yes],
+         [gl_cv_onwards_func_timespec_get=no])
+     else
+       gl_cv_onwards_func_timespec_get=no
+     fi
+     case "$host_os" in
+       linux*-android*)
+         if test $gl_cv_onwards_func_timespec_get = no; then
+           gl_cv_onwards_func_timespec_get='future OS version'
+         fi
+         ;;
+     esac
+    ])
+  case "$gl_cv_onwards_func_timespec_get" in
+    future*) gl_cv_func_timespec_get=no ;;
+    *)       gl_cv_func_timespec_get=$gl_cv_onwards_func_timespec_get ;;
+  esac
 ])
 
 AC_DEFUN([gl_GETTIME_RES],
diff --git a/m4/gnulib-common.m4 b/m4/gnulib-common.m4
index 2db3376b01e..c0181abdc50 100644
--- a/m4/gnulib-common.m4
+++ b/m4/gnulib-common.m4
@@ -1,4 +1,4 @@
-# gnulib-common.m4 serial 76
+# gnulib-common.m4 serial 80
 dnl Copyright (C) 2007-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -38,6 +38,11 @@ AC_DEFUN([gl_COMMON_BODY], [
        AIX system header files and several gnulib header files use precisely
        this syntax with 'extern'.  */
 #  define _Noreturn [[noreturn]]
+# elif (defined __clang__ && __clang_major__ < 16 \
+        && defined _GL_WORK_AROUND_LLVM_BUG_59792)
+   /* Compile with -D_GL_WORK_AROUND_LLVM_BUG_59792 to work around
+      that rare LLVM bug, though you may get many false-alarm warnings.  */
+#  define _Noreturn
 # elif ((!defined __cplusplus || defined __clang__) \
         && (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) \
             || (!defined __STRICT_ANSI__ \
@@ -119,29 +124,35 @@ AC_DEFUN([gl_COMMON_BODY], [
    by the Nth argument of the function is the size of the returned memory 
block.
  */
 /* Applies to: function, pointer to function, function types.  */
-#if _GL_HAS_ATTRIBUTE (alloc_size)
-# define _GL_ATTRIBUTE_ALLOC_SIZE(args) __attribute__ ((__alloc_size__ args))
-#else
-# define _GL_ATTRIBUTE_ALLOC_SIZE(args)
+#ifndef _GL_ATTRIBUTE_ALLOC_SIZE
+# if _GL_HAS_ATTRIBUTE (alloc_size)
+#  define _GL_ATTRIBUTE_ALLOC_SIZE(args) __attribute__ ((__alloc_size__ args))
+# else
+#  define _GL_ATTRIBUTE_ALLOC_SIZE(args)
+# endif
 #endif
 
 /* _GL_ATTRIBUTE_ALWAYS_INLINE tells that the compiler should always inline the
    function and report an error if it cannot do so.  */
 /* Applies to: function.  */
-#if _GL_HAS_ATTRIBUTE (always_inline)
-# define _GL_ATTRIBUTE_ALWAYS_INLINE __attribute__ ((__always_inline__))
-#else
-# define _GL_ATTRIBUTE_ALWAYS_INLINE
+#ifndef _GL_ATTRIBUTE_ALWAYS_INLINE
+# if _GL_HAS_ATTRIBUTE (always_inline)
+#  define _GL_ATTRIBUTE_ALWAYS_INLINE __attribute__ ((__always_inline__))
+# else
+#  define _GL_ATTRIBUTE_ALWAYS_INLINE
+# endif
 #endif
 
 /* _GL_ATTRIBUTE_ARTIFICIAL declares that the function is not important to show
     in stack traces when debugging.  The compiler should omit the function from
     stack traces.  */
 /* Applies to: function.  */
-#if _GL_HAS_ATTRIBUTE (artificial)
-# define _GL_ATTRIBUTE_ARTIFICIAL __attribute__ ((__artificial__))
-#else
-# define _GL_ATTRIBUTE_ARTIFICIAL
+#ifndef _GL_ATTRIBUTE_ARTIFICIAL
+# if _GL_HAS_ATTRIBUTE (artificial)
+#  define _GL_ATTRIBUTE_ARTIFICIAL __attribute__ ((__artificial__))
+# else
+#  define _GL_ATTRIBUTE_ARTIFICIAL
+# endif
 #endif
 
 /* _GL_ATTRIBUTE_COLD declares that the function is rarely executed.  */
@@ -149,14 +160,16 @@ AC_DEFUN([gl_COMMON_BODY], [
 /* Avoid __attribute__ ((cold)) on MinGW; see thread starting at
    <https://lists.gnu.org/r/emacs-devel/2019-04/msg01152.html>.
    Also, Oracle Studio 12.6 requires 'cold' not '__cold__'.  */
-#if _GL_HAS_ATTRIBUTE (cold) && !defined __MINGW32__
-# ifndef __SUNPRO_C
-#  define _GL_ATTRIBUTE_COLD __attribute__ ((__cold__))
+#ifndef _GL_ATTRIBUTE_COLD
+# if _GL_HAS_ATTRIBUTE (cold) && !defined __MINGW32__
+#  ifndef __SUNPRO_C
+#   define _GL_ATTRIBUTE_COLD __attribute__ ((__cold__))
+#  else
+#   define _GL_ATTRIBUTE_COLD __attribute__ ((cold))
+#  endif
 # else
-#  define _GL_ATTRIBUTE_COLD __attribute__ ((cold))
+#  define _GL_ATTRIBUTE_COLD
 # endif
-#else
-# define _GL_ATTRIBUTE_COLD
 #endif
 
 /* _GL_ATTRIBUTE_CONST declares that it is OK for a compiler to omit duplicate
@@ -166,10 +179,12 @@ AC_DEFUN([gl_COMMON_BODY], [
    forever, and does not call longjmp.
    (This attribute is stricter than _GL_ATTRIBUTE_PURE.)  */
 /* Applies to: functions.  */
-#if _GL_HAS_ATTRIBUTE (const)
-# define _GL_ATTRIBUTE_CONST __attribute__ ((__const__))
-#else
-# define _GL_ATTRIBUTE_CONST
+#ifndef _GL_ATTRIBUTE_CONST
+# if _GL_HAS_ATTRIBUTE (const)
+#  define _GL_ATTRIBUTE_CONST __attribute__ ((__const__))
+# else
+#  define _GL_ATTRIBUTE_CONST
+# endif
 #endif
 
 /* _GL_ATTRIBUTE_DEALLOC (F, I) declares that the function returns pointers
@@ -178,10 +193,12 @@ AC_DEFUN([gl_COMMON_BODY], [
    _GL_ATTRIBUTE_DEALLOC_FREE declares that the function returns pointers that
    can be freed via 'free'; it can be used only after declaring 'free'.  */
 /* Applies to: functions.  Cannot be used on inline functions.  */
-#if _GL_GNUC_PREREQ (11, 0)
-# define _GL_ATTRIBUTE_DEALLOC(f, i) __attribute__ ((__malloc__ (f, i)))
-#else
-# define _GL_ATTRIBUTE_DEALLOC(f, i)
+#ifndef _GL_ATTRIBUTE_DEALLOC
+# if _GL_GNUC_PREREQ (11, 0)
+#  define _GL_ATTRIBUTE_DEALLOC(f, i) __attribute__ ((__malloc__ (f, i)))
+# else
+#  define _GL_ATTRIBUTE_DEALLOC(f, i)
+# endif
 #endif
 /* If gnulib's <string.h> or <wchar.h> has already defined this macro, continue
    to use this earlier definition, since <stdlib.h> may not have been included
@@ -205,16 +222,18 @@ AC_DEFUN([gl_COMMON_BODY], [
      - enumeration, enumeration item,
      - typedef,
    in C++ also: namespace, class, template specialization.  */
-#ifdef __has_c_attribute
-# if __has_c_attribute (__deprecated__)
-#  define _GL_ATTRIBUTE_DEPRECATED [[__deprecated__]]
-# endif
-#endif
-#if !defined _GL_ATTRIBUTE_DEPRECATED && _GL_HAS_ATTRIBUTE (deprecated)
-# define _GL_ATTRIBUTE_DEPRECATED __attribute__ ((__deprecated__))
-#endif
 #ifndef _GL_ATTRIBUTE_DEPRECATED
-# define _GL_ATTRIBUTE_DEPRECATED
+# ifdef __has_c_attribute
+#  if __has_c_attribute (__deprecated__)
+#   define _GL_ATTRIBUTE_DEPRECATED [[__deprecated__]]
+#  endif
+# endif
+# if !defined _GL_ATTRIBUTE_DEPRECATED && _GL_HAS_ATTRIBUTE (deprecated)
+#  define _GL_ATTRIBUTE_DEPRECATED __attribute__ ((__deprecated__))
+# endif
+# ifndef _GL_ATTRIBUTE_DEPRECATED
+#  define _GL_ATTRIBUTE_DEPRECATED
+# endif
 #endif
 
 /* _GL_ATTRIBUTE_ERROR(msg) requests an error if a function is called and
@@ -222,24 +241,28 @@ AC_DEFUN([gl_COMMON_BODY], [
    _GL_ATTRIBUTE_WARNING(msg) requests a warning if a function is called and
    the function call is not optimized away.  */
 /* Applies to: functions.  */
-#if _GL_HAS_ATTRIBUTE (error)
-# define _GL_ATTRIBUTE_ERROR(msg) __attribute__ ((__error__ (msg)))
-# define _GL_ATTRIBUTE_WARNING(msg) __attribute__ ((__warning__ (msg)))
-#elif _GL_HAS_ATTRIBUTE (diagnose_if)
-# define _GL_ATTRIBUTE_ERROR(msg) __attribute__ ((__diagnose_if__ (1, msg, 
"error")))
-# define _GL_ATTRIBUTE_WARNING(msg) __attribute__ ((__diagnose_if__ (1, msg, 
"warning")))
-#else
-# define _GL_ATTRIBUTE_ERROR(msg)
-# define _GL_ATTRIBUTE_WARNING(msg)
+#if !(defined _GL_ATTRIBUTE_ERROR && defined _GL_ATTRIBUTE_WARNING)
+# if _GL_HAS_ATTRIBUTE (error)
+#  define _GL_ATTRIBUTE_ERROR(msg) __attribute__ ((__error__ (msg)))
+#  define _GL_ATTRIBUTE_WARNING(msg) __attribute__ ((__warning__ (msg)))
+# elif _GL_HAS_ATTRIBUTE (diagnose_if)
+#  define _GL_ATTRIBUTE_ERROR(msg) __attribute__ ((__diagnose_if__ (1, msg, 
"error")))
+#  define _GL_ATTRIBUTE_WARNING(msg) __attribute__ ((__diagnose_if__ (1, msg, 
"warning")))
+# else
+#  define _GL_ATTRIBUTE_ERROR(msg)
+#  define _GL_ATTRIBUTE_WARNING(msg)
+# endif
 #endif
 
 /* _GL_ATTRIBUTE_EXTERNALLY_VISIBLE declares that the entity should remain
    visible to debuggers etc., even with '-fwhole-program'.  */
 /* Applies to: functions, variables.  */
-#if _GL_HAS_ATTRIBUTE (externally_visible)
-# define _GL_ATTRIBUTE_EXTERNALLY_VISIBLE __attribute__ ((externally_visible))
-#else
-# define _GL_ATTRIBUTE_EXTERNALLY_VISIBLE
+#ifndef _GL_ATTRIBUTE_EXTERNALLY_VISIBLE
+# if _GL_HAS_ATTRIBUTE (externally_visible)
+#  define _GL_ATTRIBUTE_EXTERNALLY_VISIBLE __attribute__ ((externally_visible))
+# else
+#  define _GL_ATTRIBUTE_EXTERNALLY_VISIBLE
+# endif
 #endif
 
 /* _GL_ATTRIBUTE_FALLTHROUGH declares that it is not a programming mistake if
@@ -247,16 +270,18 @@ AC_DEFUN([gl_COMMON_BODY], [
    'default' label.  The compiler should not warn in this case.  */
 /* Applies to: Empty statement (;), inside a 'switch' statement.  */
 /* Always expands to something.  */
-#ifdef __has_c_attribute
-# if __has_c_attribute (__fallthrough__)
-#  define _GL_ATTRIBUTE_FALLTHROUGH [[__fallthrough__]]
-# endif
-#endif
-#if !defined _GL_ATTRIBUTE_FALLTHROUGH && _GL_HAS_ATTRIBUTE (fallthrough)
-# define _GL_ATTRIBUTE_FALLTHROUGH __attribute__ ((__fallthrough__))
-#endif
 #ifndef _GL_ATTRIBUTE_FALLTHROUGH
-# define _GL_ATTRIBUTE_FALLTHROUGH ((void) 0)
+# ifdef __has_c_attribute
+#  if __has_c_attribute (__fallthrough__)
+#   define _GL_ATTRIBUTE_FALLTHROUGH [[__fallthrough__]]
+#  endif
+# endif
+# if !defined _GL_ATTRIBUTE_FALLTHROUGH && _GL_HAS_ATTRIBUTE (fallthrough)
+#  define _GL_ATTRIBUTE_FALLTHROUGH __attribute__ ((__fallthrough__))
+# endif
+# ifndef _GL_ATTRIBUTE_FALLTHROUGH
+#  define _GL_ATTRIBUTE_FALLTHROUGH ((void) 0)
+# endif
 #endif
 
 /* _GL_ATTRIBUTE_FORMAT ((ARCHETYPE, STRING-INDEX, FIRST-TO-CHECK))
@@ -270,10 +295,12 @@ AC_DEFUN([gl_COMMON_BODY], [
    If FIRST-TO-CHECK is not 0, arguments starting at FIRST-TO_CHECK
    are suitable for the format string.  */
 /* Applies to: functions.  */
-#if _GL_HAS_ATTRIBUTE (format)
-# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec))
-#else
-# define _GL_ATTRIBUTE_FORMAT(spec)
+#ifndef _GL_ATTRIBUTE_FORMAT
+# if _GL_HAS_ATTRIBUTE (format)
+#  define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec))
+# else
+#  define _GL_ATTRIBUTE_FORMAT(spec)
+# endif
 #endif
 
 /* _GL_ATTRIBUTE_LEAF declares that if the function is called from some other
@@ -281,19 +308,23 @@ AC_DEFUN([gl_COMMON_BODY], [
    exception handling.  This declaration lets the compiler optimize that unit
    more aggressively.  */
 /* Applies to: functions.  */
-#if _GL_HAS_ATTRIBUTE (leaf)
-# define _GL_ATTRIBUTE_LEAF __attribute__ ((__leaf__))
-#else
-# define _GL_ATTRIBUTE_LEAF
+#ifndef _GL_ATTRIBUTE_LEAF
+# if _GL_HAS_ATTRIBUTE (leaf)
+#  define _GL_ATTRIBUTE_LEAF __attribute__ ((__leaf__))
+# else
+#  define _GL_ATTRIBUTE_LEAF
+# endif
 #endif
 
 /* _GL_ATTRIBUTE_MALLOC declares that the function returns a pointer to freshly
    allocated memory.  */
 /* Applies to: functions.  */
-#if _GL_HAS_ATTRIBUTE (malloc)
-# define _GL_ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
-#else
-# define _GL_ATTRIBUTE_MALLOC
+#ifndef _GL_ATTRIBUTE_MALLOC
+# if _GL_HAS_ATTRIBUTE (malloc)
+#  define _GL_ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
+# else
+#  define _GL_ATTRIBUTE_MALLOC
+# endif
 #endif
 
 /* _GL_ATTRIBUTE_MAY_ALIAS declares that pointers to the type may point to the
@@ -301,10 +332,12 @@ AC_DEFUN([gl_COMMON_BODY], [
    strict aliasing optimization.  */
 /* Applies to: types.  */
 /* Oracle Studio 12.6 mishandles may_alias despite __has_attribute OK.  */
-#if _GL_HAS_ATTRIBUTE (may_alias) && !defined __SUNPRO_C
-# define _GL_ATTRIBUTE_MAY_ALIAS __attribute__ ((__may_alias__))
-#else
-# define _GL_ATTRIBUTE_MAY_ALIAS
+#ifndef _GL_ATTRIBUTE_MAY_ALIAS
+# if _GL_HAS_ATTRIBUTE (may_alias) && !defined __SUNPRO_C
+#  define _GL_ATTRIBUTE_MAY_ALIAS __attribute__ ((__may_alias__))
+# else
+#  define _GL_ATTRIBUTE_MAY_ALIAS
+# endif
 #endif
 
 /* _GL_ATTRIBUTE_MAYBE_UNUSED declares that it is not a programming mistake if
@@ -318,14 +351,22 @@ AC_DEFUN([gl_COMMON_BODY], [
    in C++ also: class.  */
 /* In C++ and C23, this is spelled [[__maybe_unused__]].
    GCC's syntax is __attribute__ ((__unused__)).
-   clang supports both syntaxes.  */
-#ifdef __has_c_attribute
-# if __has_c_attribute (__maybe_unused__)
-#  define _GL_ATTRIBUTE_MAYBE_UNUSED [[__maybe_unused__]]
-# endif
-#endif
+   clang supports both syntaxes.  Except that with clang ≥ 6, < 10, in C++ 
mode,
+   __has_c_attribute (__maybe_unused__) yields true but the use of
+   [[__maybe_unused__]] nevertheless produces a warning.  */
 #ifndef _GL_ATTRIBUTE_MAYBE_UNUSED
-# define _GL_ATTRIBUTE_MAYBE_UNUSED _GL_ATTRIBUTE_UNUSED
+# if defined __clang__ && defined __cplusplus
+#  if __clang_major__ >= 10
+#   define _GL_ATTRIBUTE_MAYBE_UNUSED [[__maybe_unused__]]
+#  endif
+# elif defined __has_c_attribute
+#  if __has_c_attribute (__maybe_unused__)
+#   define _GL_ATTRIBUTE_MAYBE_UNUSED [[__maybe_unused__]]
+#  endif
+# endif
+# ifndef _GL_ATTRIBUTE_MAYBE_UNUSED
+#  define _GL_ATTRIBUTE_MAYBE_UNUSED _GL_ATTRIBUTE_UNUSED
+# endif
 #endif
 /* Alternative spelling of this macro, for convenience and for
    compatibility with glibc/include/libc-symbols.h.  */
@@ -337,25 +378,38 @@ AC_DEFUN([gl_COMMON_BODY], [
    discard the return value.  The compiler may warn if the caller does not use
    the return value, unless the caller uses something like ignore_value.  */
 /* Applies to: function, enumeration, class.  */
-#ifdef __has_c_attribute
-# if __has_c_attribute (__nodiscard__)
-#  define _GL_ATTRIBUTE_NODISCARD [[__nodiscard__]]
-# endif
-#endif
-#if !defined _GL_ATTRIBUTE_NODISCARD && _GL_HAS_ATTRIBUTE (warn_unused_result)
-# define _GL_ATTRIBUTE_NODISCARD __attribute__ ((__warn_unused_result__))
-#endif
 #ifndef _GL_ATTRIBUTE_NODISCARD
-# define _GL_ATTRIBUTE_NODISCARD
+# if defined __clang__ && defined __cplusplus
+  /* With clang up to 15.0.6 (at least), in C++ mode, [[__nodiscard__]] 
produces
+     a warning.
+     The 1000 below means a yet unknown threshold.  When clang++ version X
+     starts supporting [[__nodiscard__]] without warning about it, you can
+     replace the 1000 with X.  */
+#  if __clang_major__ >= 1000
+#   define _GL_ATTRIBUTE_NODISCARD [[__nodiscard__]]
+#  endif
+# elif defined __has_c_attribute
+#  if __has_c_attribute (__nodiscard__)
+#   define _GL_ATTRIBUTE_NODISCARD [[__nodiscard__]]
+#  endif
+# endif
+# if !defined _GL_ATTRIBUTE_NODISCARD && _GL_HAS_ATTRIBUTE (warn_unused_result)
+#  define _GL_ATTRIBUTE_NODISCARD __attribute__ ((__warn_unused_result__))
+# endif
+# ifndef _GL_ATTRIBUTE_NODISCARD
+#  define _GL_ATTRIBUTE_NODISCARD
+# endif
 #endif
 
 /* _GL_ATTRIBUTE_NOINLINE tells that the compiler should not inline the
    function.  */
 /* Applies to: functions.  */
-#if _GL_HAS_ATTRIBUTE (noinline)
-# define _GL_ATTRIBUTE_NOINLINE __attribute__ ((__noinline__))
-#else
-# define _GL_ATTRIBUTE_NOINLINE
+#ifndef _GL_ATTRIBUTE_NOINLINE
+# if _GL_HAS_ATTRIBUTE (noinline)
+#  define _GL_ATTRIBUTE_NOINLINE __attribute__ ((__noinline__))
+# else
+#  define _GL_ATTRIBUTE_NOINLINE
+# endif
 #endif
 
 /* _GL_ATTRIBUTE_NONNULL ((N1, N2,...)) declares that the arguments N1, N2,...
@@ -363,20 +417,24 @@ AC_DEFUN([gl_COMMON_BODY], [
    _GL_ATTRIBUTE_NONNULL () declares that all pointer arguments must not be
    null.  */
 /* Applies to: functions.  */
-#if _GL_HAS_ATTRIBUTE (nonnull)
-# define _GL_ATTRIBUTE_NONNULL(args) __attribute__ ((__nonnull__ args))
-#else
-# define _GL_ATTRIBUTE_NONNULL(args)
+#ifndef _GL_ATTRIBUTE_NONNULL
+# if _GL_HAS_ATTRIBUTE (nonnull)
+#  define _GL_ATTRIBUTE_NONNULL(args) __attribute__ ((__nonnull__ args))
+# else
+#  define _GL_ATTRIBUTE_NONNULL(args)
+# endif
 #endif
 
 /* _GL_ATTRIBUTE_NONSTRING declares that the contents of a character array is
    not meant to be NUL-terminated.  */
 /* Applies to: struct/union members and variables that are arrays of element
    type '[[un]signed] char'.  */
-#if _GL_HAS_ATTRIBUTE (nonstring)
-# define _GL_ATTRIBUTE_NONSTRING __attribute__ ((__nonstring__))
-#else
-# define _GL_ATTRIBUTE_NONSTRING
+#ifndef _GL_ATTRIBUTE_NONSTRING
+# if _GL_HAS_ATTRIBUTE (nonstring)
+#  define _GL_ATTRIBUTE_NONSTRING __attribute__ ((__nonstring__))
+# else
+#  define _GL_ATTRIBUTE_NONSTRING
+# endif
 #endif
 
 /* There is no _GL_ATTRIBUTE_NORETURN; use _Noreturn instead.  */
@@ -384,10 +442,12 @@ AC_DEFUN([gl_COMMON_BODY], [
 /* _GL_ATTRIBUTE_NOTHROW declares that the function does not throw exceptions.
  */
 /* Applies to: functions.  */
-#if _GL_HAS_ATTRIBUTE (nothrow) && !defined __cplusplus
-# define _GL_ATTRIBUTE_NOTHROW __attribute__ ((__nothrow__))
-#else
-# define _GL_ATTRIBUTE_NOTHROW
+#ifndef _GL_ATTRIBUTE_NOTHROW
+# if _GL_HAS_ATTRIBUTE (nothrow) && !defined __cplusplus
+#  define _GL_ATTRIBUTE_NOTHROW __attribute__ ((__nothrow__))
+# else
+#  define _GL_ATTRIBUTE_NOTHROW
+# endif
 #endif
 
 /* _GL_ATTRIBUTE_PACKED declares:
@@ -396,10 +456,12 @@ AC_DEFUN([gl_COMMON_BODY], [
    minimizing the memory required.  */
 /* Applies to: struct members, struct, union,
    in C++ also: class.  */
-#if _GL_HAS_ATTRIBUTE (packed)
-# define _GL_ATTRIBUTE_PACKED __attribute__ ((__packed__))
-#else
-# define _GL_ATTRIBUTE_PACKED
+#ifndef _GL_ATTRIBUTE_PACKED
+# if _GL_HAS_ATTRIBUTE (packed)
+#  define _GL_ATTRIBUTE_PACKED __attribute__ ((__packed__))
+# else
+#  define _GL_ATTRIBUTE_PACKED
+# endif
 #endif
 
 /* _GL_ATTRIBUTE_PURE declares that It is OK for a compiler to omit duplicate
@@ -409,19 +471,23 @@ AC_DEFUN([gl_COMMON_BODY], [
    observable state, and always returns exactly once.
    (This attribute is looser than _GL_ATTRIBUTE_CONST.)  */
 /* Applies to: functions.  */
-#if _GL_HAS_ATTRIBUTE (pure)
-# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
-#else
-# define _GL_ATTRIBUTE_PURE
+#ifndef _GL_ATTRIBUTE_PURE
+# if _GL_HAS_ATTRIBUTE (pure)
+#  define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
+# else
+#  define _GL_ATTRIBUTE_PURE
+# endif
 #endif
 
 /* _GL_ATTRIBUTE_RETURNS_NONNULL declares that the function's return value is
    a non-NULL pointer.  */
 /* Applies to: functions.  */
-#if _GL_HAS_ATTRIBUTE (returns_nonnull)
-# define _GL_ATTRIBUTE_RETURNS_NONNULL __attribute__ ((__returns_nonnull__))
-#else
-# define _GL_ATTRIBUTE_RETURNS_NONNULL
+#ifndef _GL_ATTRIBUTE_RETURNS_NONNULL
+# if _GL_HAS_ATTRIBUTE (returns_nonnull)
+#  define _GL_ATTRIBUTE_RETURNS_NONNULL __attribute__ ((__returns_nonnull__))
+# else
+#  define _GL_ATTRIBUTE_RETURNS_NONNULL
+# endif
 #endif
 
 /* _GL_ATTRIBUTE_SENTINEL(pos) declares that the variadic function expects a
@@ -429,17 +495,21 @@ AC_DEFUN([gl_COMMON_BODY], [
    _GL_ATTRIBUTE_SENTINEL () - The last argument is NULL (requires C99).
    _GL_ATTRIBUTE_SENTINEL ((N)) - The (N+1)st argument from the end is NULL.  
*/
 /* Applies to: functions.  */
-#if _GL_HAS_ATTRIBUTE (sentinel)
-# define _GL_ATTRIBUTE_SENTINEL(pos) __attribute__ ((__sentinel__ pos))
-#else
-# define _GL_ATTRIBUTE_SENTINEL(pos)
+#ifndef _GL_ATTRIBUTE_SENTINEL
+# if _GL_HAS_ATTRIBUTE (sentinel)
+#  define _GL_ATTRIBUTE_SENTINEL(pos) __attribute__ ((__sentinel__ pos))
+# else
+#  define _GL_ATTRIBUTE_SENTINEL(pos)
+# endif
 #endif
 
 /* A helper macro.  Don't use it directly.  */
-#if _GL_HAS_ATTRIBUTE (unused)
-# define _GL_ATTRIBUTE_UNUSED __attribute__ ((__unused__))
-#else
-# define _GL_ATTRIBUTE_UNUSED
+#ifndef _GL_ATTRIBUTE_UNUSED
+# if _GL_HAS_ATTRIBUTE (unused)
+#  define _GL_ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+# else
+#  define _GL_ATTRIBUTE_UNUSED
+# endif
 #endif
 
 ]dnl There is no _GL_ATTRIBUTE_VISIBILITY; see m4/visibility.m4 instead.
@@ -450,10 +520,12 @@ AC_DEFUN([gl_COMMON_BODY], [
 /* Applies to: label (both in C and C++).  */
 /* Note that g++ < 4.5 does not support the '__attribute__ ((__unused__)) ;'
    syntax.  But clang does.  */
-#if !(defined __cplusplus && !_GL_GNUC_PREREQ (4, 5)) || defined __clang__
-# define _GL_UNUSED_LABEL _GL_ATTRIBUTE_UNUSED
-#else
-# define _GL_UNUSED_LABEL
+#ifndef _GL_UNUSED_LABEL
+# if !(defined __cplusplus && !_GL_GNUC_PREREQ (4, 5)) || defined __clang__
+#  define _GL_UNUSED_LABEL _GL_ATTRIBUTE_UNUSED
+# else
+#  define _GL_UNUSED_LABEL
+# endif
 #endif
 ])
   AH_VERBATIM([async_safe],
@@ -1026,8 +1098,21 @@ AC_DEFUN([gl_CONDITIONAL_HEADER],
 dnl gl_CHECK_FUNCS_ANDROID([func], [[#include <foo.h>]])
 dnl is like AC_CHECK_FUNCS([func]), taking into account a portability problem
 dnl on Android.
-dnl Namely, if func was added to Android API level, say, 28, then the libc.so
-dnl has the symbol func always, whereas the header file <foo.h> declares func
+dnl
+dnl When code is compiled on Android, it is in the context of a certain
+dnl "Android API level", which indicates the minimum version of Android on
+dnl which the app can be installed. In other words, you don't compile for a
+dnl specific version of Android. You compile for all versions of Android,
+dnl onwards from the given API level.
+dnl Thus, the question "does the OS have the function func" has three possible
+dnl answers:
+dnl   - yes, in all versions starting from the given API level,
+dnl   - no, in no version,
+dnl   - not in the given API level, but in a later version of Android.
+dnl
+dnl In detail, this works as follows:
+dnl If func was added to Android API level, say, 28, then the libc.so has the
+dnl symbol func always, whereas the header file <foo.h> declares func
 dnl conditionally:
 dnl   #if __ANDROID_API__ >= 28
 dnl   ... func (...) __INTRODUCED_IN(28);
@@ -1035,15 +1120,55 @@ dnl   #endif
 dnl Thus, when compiling with "clang -target armv7a-unknown-linux-android28",
 dnl the function func is declared and exists in libc.
 dnl Whereas when compiling with "clang -target armv7a-unknown-linux-android27",
-dnl the function func is not declared but exists in libc. We need to treat this
-dnl case like the case where func does not exist.
+dnl the function func is not declared but exists in libc.
+dnl
+dnl This macro sets two variables:
+dnl   - gl_cv_onwards_func_<func>   to yes / no / "future OS version"
+dnl   - ac_cv_func_<func>           to yes / no / no
+dnl The first variable allows to distinguish all three cases.
+dnl The second variable is set, so that an invocation
+dnl   gl_CHECK_FUNCS_ANDROID([func], [[#include <foo.h>]])
+dnl can be used as a drop-in replacement for
+dnl   AC_CHECK_FUNCS([func]).
 AC_DEFUN([gl_CHECK_FUNCS_ANDROID],
 [
-  AC_CHECK_DECL([$1], , , [$2])
-  if test $ac_cv_have_decl_[$1] = yes; then
-    AC_CHECK_FUNCS([$1])
-  else
-    ac_cv_func_[$1]=no
+  AC_REQUIRE([AC_CANONICAL_HOST])
+  AC_CACHE_CHECK([for [$1]],
+    [[gl_cv_onwards_func_][$1]],
+    [gl_SILENT([
+       case "$host_os" in
+         linux*-android*)
+           AC_CHECK_DECL([$1], , , [$2])
+           if test $[ac_cv_have_decl_][$1] = yes; then
+             AC_CHECK_FUNC([[$1]])
+             if test $[ac_cv_func_][$1] = yes; then
+               [gl_cv_onwards_func_][$1]=yes
+             else
+               dnl The function is declared but does not exist. This should not
+               dnl happen normally. But anyway, we know that a future version
+               dnl of Android will have the function.
+               [gl_cv_onwards_func_][$1]='future OS version'
+             fi
+           else
+             [gl_cv_onwards_func_][$1]='future OS version'
+           fi
+           ;;
+         *)
+           AC_CHECK_FUNC([$1])
+           [gl_cv_onwards_func_][$1]=$[ac_cv_func_][$1]
+           ;;
+       esac
+      ])
+    ])
+  case "$[gl_cv_onwards_func_][$1]" in
+    future*) [ac_cv_func_][$1]=no ;;
+    *)       [ac_cv_func_][$1]=$[gl_cv_onwards_func_][$1] ;;
+  esac
+  if test $[ac_cv_func_][$1] = yes; then
+    AC_DEFINE([HAVE_]m4_translit([[$1]],
+                                 [abcdefghijklmnopqrstuvwxyz],
+                                 [ABCDEFGHIJKLMNOPQRSTUVWXYZ]),
+              [1], [Define to 1 if you have the `$1' function.])
   fi
 ])
 
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
index 10c74fa2392..0658652a99e 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -44,6 +44,7 @@ AC_DEFUN([gl_EARLY],
 
   # Code from module absolute-header:
   # Code from module acl-permissions:
+  # Code from module alignasof:
   # Code from module alloca-opt:
   # Code from module allocator:
   # Code from module assert-h:
@@ -170,7 +171,6 @@ AC_DEFUN([gl_EARLY],
   # Code from module ssize_t:
   # Code from module stat-time:
   # Code from module std-gnu11:
-  # Code from module stdalign:
   # Code from module stdbool:
   # Code from module stdckdint:
   # Code from module stddef:
@@ -231,6 +231,7 @@ AC_DEFUN([gl_INIT],
   gl_source_base='lib'
   gl_source_base_prefix=
   gl_FUNC_ACL
+  gl_ALIGNASOF
   gl_FUNC_ALLOCA
   gl_CONDITIONAL_HEADER([alloca.h])
   AC_PROG_MKDIR_P
@@ -248,7 +249,7 @@ AC_DEFUN([gl_INIT],
   gl_STDLIB_MODULE_INDICATOR([canonicalize_file_name])
   gl_STDLIB_MODULE_INDICATOR([realpath])
   AC_REQUIRE([AC_C_RESTRICT])
-  AC_CHECK_FUNCS_ONCE([readlinkat])
+  gl_CHECK_FUNCS_ANDROID([readlinkat], [[#include <unistd.h>]])
   gl_CLOCK_TIME
   gl_MODULE_INDICATOR([close-stream])
   gl_FUNC_COPY_FILE_RANGE
@@ -344,7 +345,8 @@ AC_DEFUN([gl_INIT],
   gl_SYS_STAT_MODULE_INDICATOR([futimens])
   AC_REQUIRE([AC_CANONICAL_HOST])
   gl_GETLOADAVG
-  gl_CONDITIONAL([GL_COND_OBJ_GETLOADAVG], [test $HAVE_GETLOADAVG = 0])
+  gl_CONDITIONAL([GL_COND_OBJ_GETLOADAVG],
+                 [test $HAVE_GETLOADAVG = 0 || test $REPLACE_GETLOADAVG = 1])
   AM_COND_IF([GL_COND_OBJ_GETLOADAVG], [
     gl_PREREQ_GETLOADAVG
   ])
@@ -404,7 +406,8 @@ AC_DEFUN([gl_INIT],
   fi
   gl_STRING_MODULE_INDICATOR([memmem])
   gl_FUNC_MEMPCPY
-  gl_CONDITIONAL([GL_COND_OBJ_MEMPCPY], [test $HAVE_MEMPCPY = 0])
+  gl_CONDITIONAL([GL_COND_OBJ_MEMPCPY],
+                 [test $HAVE_MEMPCPY = 0 || test $REPLACE_MEMPCPY = 1])
   AM_COND_IF([GL_COND_OBJ_MEMPCPY], [
     gl_PREREQ_MEMPCPY
   ])
@@ -423,7 +426,8 @@ AC_DEFUN([gl_INIT],
   gl_STRING_MODULE_INDICATOR([memset_explicit])
   gl_MINMAX
   gl_FUNC_MKOSTEMP
-  gl_CONDITIONAL([GL_COND_OBJ_MKOSTEMP], [test $HAVE_MKOSTEMP = 0])
+  gl_CONDITIONAL([GL_COND_OBJ_MKOSTEMP],
+                 [test $HAVE_MKOSTEMP = 0 || test $REPLACE_MKOSTEMP = 1])
   AM_COND_IF([GL_COND_OBJ_MKOSTEMP], [
     gl_PREREQ_MKOSTEMP
   ])
@@ -495,9 +499,6 @@ AC_DEFUN([gl_INIT],
   gt_TYPE_SSIZE_T
   gl_STAT_TIME
   gl_STAT_BIRTHTIME
-  gl_STDALIGN_H
-  gl_CONDITIONAL_HEADER([stdalign.h])
-  AC_PROG_MKDIR_P
   gl_C_BOOL
   AC_CHECK_HEADERS_ONCE([stdckdint.h])
   if test $ac_cv_header_stdckdint_h = yes; then
@@ -548,7 +549,8 @@ AC_DEFUN([gl_INIT],
   gl_STDLIB_H_REQUIRE_DEFAULTS
   AC_PROG_MKDIR_P
   gl_FUNC_STPCPY
-  gl_CONDITIONAL([GL_COND_OBJ_STPCPY], [test $HAVE_STPCPY = 0])
+  gl_CONDITIONAL([GL_COND_OBJ_STPCPY],
+                 [test $HAVE_STPCPY = 0 || test $REPLACE_STPCPY = 1])
   AM_COND_IF([GL_COND_OBJ_STPCPY], [
     gl_PREREQ_STPCPY
   ])
@@ -973,7 +975,7 @@ AC_DEFUN([gl_INIT],
   if test $HAVE_FUTIMENS = 0 || test $REPLACE_FUTIMENS = 1; then
     func_gl_gnulib_m4code_utimens
   fi
-  if case $host_os in mingw*) false;; *) test $HAVE_GETLOADAVG = 0;; esac; then
+  if case $host_os in mingw*) false;; *) test $HAVE_GETLOADAVG = 0 || test 
$REPLACE_GETLOADAVG = 1;; esac; then
     func_gl_gnulib_m4code_open
   fi
   if test $REPLACE_GETOPT = 1; then
@@ -1371,7 +1373,6 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/signal.in.h
   lib/stat-time.c
   lib/stat-time.h
-  lib/stdalign.in.h
   lib/stdckdint.in.h
   lib/stddef.in.h
   lib/stdint.in.h
diff --git a/m4/inttypes.m4 b/m4/inttypes.m4
index bf2eab2ba31..e7efbe94167 100644
--- a/m4/inttypes.m4
+++ b/m4/inttypes.m4
@@ -1,4 +1,4 @@
-# inttypes.m4 serial 36
+# inttypes.m4 serial 37
 dnl Copyright (C) 2006-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -170,6 +170,10 @@ AC_DEFUN([gl_INTTYPES_H_DEFAULTS],
   HAVE_DECL_STRTOIMAX=1; AC_SUBST([HAVE_DECL_STRTOIMAX])
   HAVE_DECL_STRTOUMAX=1; AC_SUBST([HAVE_DECL_STRTOUMAX])
   HAVE_IMAXDIV_T=1;      AC_SUBST([HAVE_IMAXDIV_T])
+  HAVE_IMAXABS=1;        AC_SUBST([HAVE_IMAXABS])
+  HAVE_IMAXDIV=1;        AC_SUBST([HAVE_IMAXDIV])
+  REPLACE_IMAXABS=0;     AC_SUBST([REPLACE_IMAXABS])
+  REPLACE_IMAXDIV=0;     AC_SUBST([REPLACE_IMAXDIV])
   REPLACE_STRTOIMAX=0;   AC_SUBST([REPLACE_STRTOIMAX])
   REPLACE_STRTOUMAX=0;   AC_SUBST([REPLACE_STRTOUMAX])
   INT32_MAX_LT_INTMAX_MAX=1;  AC_SUBST([INT32_MAX_LT_INTMAX_MAX])
diff --git a/m4/mempcpy.m4 b/m4/mempcpy.m4
index 55bee2ab7a2..612b77b3c11 100644
--- a/m4/mempcpy.m4
+++ b/m4/mempcpy.m4
@@ -1,4 +1,4 @@
-# mempcpy.m4 serial 12
+# mempcpy.m4 serial 14
 dnl Copyright (C) 2003-2004, 2006-2007, 2009-2023 Free Software Foundation,
 dnl Inc.
 dnl This file is free software; the Free Software Foundation
@@ -14,9 +14,12 @@ AC_DEFUN([gl_FUNC_MEMPCPY],
   AC_REQUIRE([AC_C_RESTRICT])
 
   AC_REQUIRE([gl_STRING_H_DEFAULTS])
-  AC_CHECK_FUNCS([mempcpy])
+  gl_CHECK_FUNCS_ANDROID([mempcpy], [[#include <string.h>]])
   if test $ac_cv_func_mempcpy = no; then
     HAVE_MEMPCPY=0
+    case "$gl_cv_onwards_func_mempcpy" in
+      future*) REPLACE_MEMPCPY=1 ;;
+    esac
   fi
 ])
 
diff --git a/m4/mkostemp.m4 b/m4/mkostemp.m4
index a7cfac4cb87..1b0d0d55946 100644
--- a/m4/mkostemp.m4
+++ b/m4/mkostemp.m4
@@ -1,4 +1,4 @@
-# mkostemp.m4 serial 2
+# mkostemp.m4 serial 4
 dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -11,9 +11,12 @@ AC_DEFUN([gl_FUNC_MKOSTEMP],
   dnl Persuade glibc <stdlib.h> to declare mkostemp().
   AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
 
-  AC_CHECK_FUNCS_ONCE([mkostemp])
+  gl_CHECK_FUNCS_ANDROID([mkostemp], [[#include <stdlib.h>]])
   if test $ac_cv_func_mkostemp != yes; then
     HAVE_MKOSTEMP=0
+    case "$gl_cv_onwards_func_mkostemp" in
+      future*) REPLACE_MKOSTEMP=1 ;;
+    esac
   fi
 ])
 
diff --git a/m4/nproc.m4 b/m4/nproc.m4
index 3065b7b9bff..c892ad74b7d 100644
--- a/m4/nproc.m4
+++ b/m4/nproc.m4
@@ -1,4 +1,4 @@
-# nproc.m4 serial 5
+# nproc.m4 serial 6
 dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -25,8 +25,8 @@ AC_DEFUN([gl_PREREQ_NPROC],
      #endif
     ])
 
-  AC_CHECK_FUNCS([sched_getaffinity sched_getaffinity_np \
-                  pstat_getdynamic sysmp sysctl])
+  AC_CHECK_FUNCS([sched_getaffinity_np pstat_getdynamic sysmp sysctl])
+  gl_CHECK_FUNCS_ANDROID([sched_getaffinity], [[#include <sched.h>]])
 
   dnl Test whether sched_getaffinity has the expected declaration.
   dnl glibc 2.3.[0-2]:
diff --git a/m4/pipe2.m4 b/m4/pipe2.m4
index 501f3a4303d..79de69cd1a4 100644
--- a/m4/pipe2.m4
+++ b/m4/pipe2.m4
@@ -1,4 +1,4 @@
-# pipe2.m4 serial 2
+# pipe2.m4 serial 4
 dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -11,8 +11,13 @@ AC_DEFUN([gl_FUNC_PIPE2],
   dnl Persuade glibc <unistd.h> to declare pipe2().
   AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
 
-  AC_CHECK_FUNCS_ONCE([pipe2])
+  gl_CHECK_FUNCS_ANDROID([pipe2], [[#include <unistd.h>]])
   if test $ac_cv_func_pipe2 != yes; then
     HAVE_PIPE2=0
+    case "$gl_cv_onwards_func_pipe2" in
+      future*) REPLACE_PIPE2=1 ;;
+    esac
+  else
+    REPLACE_PIPE2=1
   fi
 ])
diff --git a/m4/readlinkat.m4 b/m4/readlinkat.m4
index ffd0b8e9bc1..5c513562919 100644
--- a/m4/readlinkat.m4
+++ b/m4/readlinkat.m4
@@ -1,4 +1,4 @@
-# serial 6
+# serial 8
 # See if we need to provide readlinkat replacement.
 
 dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
@@ -12,10 +12,13 @@ AC_DEFUN([gl_FUNC_READLINKAT],
 [
   AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
   AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
-  AC_CHECK_FUNCS_ONCE([readlinkat])
+  gl_CHECK_FUNCS_ANDROID([readlinkat], [[#include <unistd.h>]])
   AC_REQUIRE([gl_FUNC_READLINK])
   if test $ac_cv_func_readlinkat = no; then
     HAVE_READLINKAT=0
+    case "$gl_cv_onwards_func_readlinkat" in
+      future*) REPLACE_READLINKAT=1 ;;
+    esac
   else
     AC_CACHE_CHECK([whether readlinkat signature is correct],
       [gl_cv_decl_readlinkat_works],
diff --git a/m4/stdalign.m4 b/m4/stdalign.m4
index b1438eeaced..f49cf8ec162 100644
--- a/m4/stdalign.m4
+++ b/m4/stdalign.m4
@@ -5,9 +5,11 @@ dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
 dnl with or without modifications, as long as this notice is preserved.
 
+dnl Written by Paul Eggert and Bruno Haible.
+
 # Prepare for substituting <stdalign.h> if it is not supported.
 
-AC_DEFUN([gl_STDALIGN_H],
+AC_DEFUN([gl_ALIGNASOF],
 [
   AC_CACHE_CHECK([for alignas and alignof],
     [gl_cv_header_working_stdalign_h],
@@ -58,77 +60,141 @@ AC_DEFUN([gl_STDALIGN_H],
       test "$gl_cv_header_working_stdalign_h" != no && break
      done])
 
-  GL_GENERATE_STDALIGN_H=false
   AS_CASE([$gl_cv_header_working_stdalign_h],
-    [no],
-      [GL_GENERATE_STDALIGN_H=true],
     [yes*keyword*],
       [AC_DEFINE([HAVE_C_ALIGNASOF], [1],
          [Define to 1 if the alignas and alignof keywords work.])])
 
-  AC_CHECK_HEADERS_ONCE([stdalign.h])
-
   dnl The "zz" puts this toward config.h's end, to avoid potential
   dnl collisions with other definitions.
   AH_VERBATIM([zzalignas],
 [#if !defined HAVE_C_ALIGNASOF && __cplusplus < 201103 && !defined alignof
 # if HAVE_STDALIGN_H
 #  include <stdalign.h>
-# else
-   /* Substitute.  Keep consistent with gnulib/lib/stdalign.in.h.  */
-#  ifndef _GL_STDALIGN_H
-#   define _GL_STDALIGN_H
-#   undef _Alignas
-#   undef _Alignof
-#   if (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112 \
-        || (defined __GNUC__ && __GNUC__ < 4 + (__GNUC_MINOR__ < 9) \
-            && !defined __clang__) \
-        || (defined __clang__ && __clang_major__ < 8))
-#    ifdef __cplusplus
-#     if (201103 <= __cplusplus || defined _MSC_VER)
-#      define _Alignof(type) alignof (type)
-#     else
-       template <class __t> struct __alignof_helper { char __a; __t __b; };
-#      define _Alignof(type) offsetof (__alignof_helper<type>, __b)
-#      define _GL_STDALIGN_NEEDS_STDDEF 1
-#     endif
+# endif
+
+/* ISO C23 alignas and alignof for platforms that lack it.
+
+   References:
+   ISO C23 (latest free draft
+   <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n3047.pdf>)
+   sections 6.5.3.4, 6.7.5, 7.15.
+   C++11 (latest free draft
+   <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf>)
+   section 18.10. */
+
+/* alignof (TYPE), also known as _Alignof (TYPE), yields the alignment
+   requirement of a structure member (i.e., slot or field) that is of
+   type TYPE, as an integer constant expression.
+
+   This differs from GCC's and clang's __alignof__ operator, which can
+   yield a better-performing alignment for an object of that type.  For
+   example, on x86 with GCC and on Linux/x86 with clang,
+   __alignof__ (double) and __alignof__ (long long) are 8, whereas
+   alignof (double) and alignof (long long) are 4 unless the option
+   '-malign-double' is used.
+
+   The result cannot be used as a value for an 'enum' constant, if you
+   want to be portable to HP-UX 10.20 cc and AIX 3.2.5 xlc.  */
+
+/* GCC releases before GCC 4.9 had a bug in _Alignof.  See GCC bug 52023
+   <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52023>.
+   clang versions < 8.0.0 have the same bug.  */
+#  if (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112 \
+       || (defined __GNUC__ && __GNUC__ < 4 + (__GNUC_MINOR__ < 9) \
+           && !defined __clang__) \
+       || (defined __clang__ && __clang_major__ < 8))
+#   undef/**/_Alignof
+#   ifdef __cplusplus
+#    if (201103 <= __cplusplus || defined _MSC_VER)
+#     define _Alignof(type) alignof (type)
 #    else
-#     define _Alignof(type) offsetof (struct { char __a; type __b; }, __b)
+      template <class __t> struct __alignof_helper { char __a; __t __b; };
+#     define _Alignof(type) offsetof (__alignof_helper<type>, __b)
 #     define _GL_STDALIGN_NEEDS_STDDEF 1
 #    endif
-#   endif
-#   if ! (defined __cplusplus && (201103 <= __cplusplus || defined _MSC_VER))
-#    define alignof _Alignof
-#   endif
-#   define __alignof_is_defined 1
-#   if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112
-#    if defined __cplusplus && (201103 <= __cplusplus || defined _MSC_VER)
-#     define _Alignas(a) alignas (a)
-#    elif (!defined __attribute__ \
-           && ((defined __APPLE__ && defined __MACH__ \
-                ? 4 < __GNUC__ + (1 <= __GNUC_MINOR__) \
-                : __GNUC__ && !defined __ibmxl__) \
-               || (4 <= __clang_major__) \
-               || (__ia64 && (61200 <= __HP_cc || 61200 <= __HP_aCC)) \
-               || __ICC || 0x590 <= __SUNPRO_C || 0x0600 <= __xlC__))
-#     define _Alignas(a) __attribute__ ((__aligned__ (a)))
-#    elif 1300 <= _MSC_VER
-#     define _Alignas(a) __declspec (align (a))
+#   else
+#    if (defined __GNUC__ && 4 <= __GNUC__) || defined __clang__
+#     define _Alignof(type) __builtin_offsetof (struct { char __a; type __b; 
}, __b)
+#    else
+#     define _Alignof(type) offsetof (struct { char __a; type __b; }, __b)
+#     define _GL_STDALIGN_NEEDS_STDDEF 1
 #    endif
 #   endif
-#   if ((defined _Alignas \
-         && !(defined __cplusplus && (201103 <= __cplusplus || defined 
_MSC_VER))) \
-        || (defined __STDC_VERSION__ && 201112 <= __STDC_VERSION__))
-#    define alignas _Alignas
-#   endif
-#   if (defined alignas \
-        || (defined __cplusplus && (201103 <= __cplusplus || defined 
_MSC_VER)))
-#    define __alignas_is_defined 1
-#   endif
-#   if _GL_STDALIGN_NEEDS_STDDEF
-#    include <stddef.h>
+#  endif
+#  if ! (defined __cplusplus && (201103 <= __cplusplus || defined _MSC_VER))
+#   undef/**/alignof
+#   define alignof _Alignof
+#  endif
+
+/* alignas (A), also known as _Alignas (A), aligns a variable or type
+   to the alignment A, where A is an integer constant expression.  For
+   example:
+
+      int alignas (8) foo;
+      struct s { int a; int alignas (8) bar; };
+
+   aligns the address of FOO and the offset of BAR to be multiples of 8.
+
+   A should be a power of two that is at least the type's alignment
+   and at most the implementation's alignment limit.  This limit is
+   2**28 on typical GNUish hosts, and 2**13 on MSVC.  To be portable
+   to MSVC through at least version 10.0, A should be an integer
+   constant, as MSVC does not support expressions such as 1 << 3.
+   To be portable to Sun C 5.11, do not align auto variables to
+   anything stricter than their default alignment.
+
+   The following C23 requirements are not supported here:
+
+     - If A is zero, alignas has no effect.
+     - alignas can be used multiple times; the strictest one wins.
+     - alignas (TYPE) is equivalent to alignas (alignof (TYPE)).
+
+   */
+# if !HAVE_STDALIGN_H
+#  if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112
+#   if defined __cplusplus && (201103 <= __cplusplus || defined _MSC_VER)
+#    define _Alignas(a) alignas (a)
+#   elif (!defined __attribute__ \
+          && ((defined __APPLE__ && defined __MACH__ \
+               ? 4 < __GNUC__ + (1 <= __GNUC_MINOR__) \
+               : __GNUC__ && !defined __ibmxl__) \
+              || (4 <= __clang_major__) \
+              || (__ia64 && (61200 <= __HP_cc || 61200 <= __HP_aCC)) \
+              || __ICC || 0x590 <= __SUNPRO_C || 0x0600 <= __xlC__))
+#    define _Alignas(a) __attribute__ ((__aligned__ (a)))
+#   elif 1300 <= _MSC_VER
+#    define _Alignas(a) __declspec (align (a))
 #   endif
-#  endif /* _GL_STDALIGN_H */
+#  endif
+#  if ((defined _Alignas \
+        && !(defined __cplusplus \
+             && (201103 <= __cplusplus || defined _MSC_VER))) \
+       || (defined __STDC_VERSION__ && 201112 <= __STDC_VERSION__))
+#   define alignas _Alignas
+#  endif
+# endif
+
+# if _GL_STDALIGN_NEEDS_STDDEF
+#  include <stddef.h>
 # endif
 #endif])
 ])
+
+AC_DEFUN([gl_STDALIGN_H],
+[
+  AC_REQUIRE([gl_ALIGNASOF])
+  if test "$gl_cv_header_working_stdalign_h" = no; then
+    GL_GENERATE_STDALIGN_H=true
+  else
+    GL_GENERATE_STDALIGN_H=false
+  fi
+
+  gl_CHECK_NEXT_HEADERS([stdalign.h])
+  if test $ac_cv_header_stdalign_h = yes; then
+    HAVE_STDALIGN_H=1
+  else
+    HAVE_STDALIGN_H=0
+  fi
+  AC_SUBST([HAVE_STDALIGN_H])
+])
diff --git a/m4/stddef_h.m4 b/m4/stddef_h.m4
index c0553d6f2ff..a2322ebb7ee 100644
--- a/m4/stddef_h.m4
+++ b/m4/stddef_h.m4
@@ -1,4 +1,4 @@
-# stddef_h.m4 serial 12
+# stddef_h.m4 serial 13
 dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -22,7 +22,14 @@ AC_DEFUN_ONCE([gl_STDDEF_H],
     [gl_cv_type_max_align_t],
     [AC_COMPILE_IFELSE(
        [AC_LANG_PROGRAM(
-          [[#include <stddef.h>
+          [[/* On FreeBSD 12.0/x86, max_align_t defined by <stddef.h> has
+               the correct alignment with the default (wrong) definition of
+               _Alignof, but a wrong alignment as soon as we activate an
+               ISO C compliant _Alignof definition.  */
+            #if ((defined __GNUC__ && 4 <= __GNUC__) || defined __clang__) && 
!defined __cplusplus
+             #define _Alignof(type) __builtin_offsetof (struct { char __a; 
type __b; }, __b)
+            #endif
+            #include <stddef.h>
             unsigned int s = sizeof (max_align_t);
             #if defined __GNUC__ || defined __clang__ || defined 
__IBM__ALIGNOF__
             int check1[2 * (__alignof__ (double) <= __alignof__ (max_align_t)) 
- 1];
diff --git a/m4/stdlib_h.m4 b/m4/stdlib_h.m4
index e96be22f583..249ef657224 100644
--- a/m4/stdlib_h.m4
+++ b/m4/stdlib_h.m4
@@ -1,4 +1,4 @@
-# stdlib_h.m4 serial 66
+# stdlib_h.m4 serial 71
 dnl Copyright (C) 2007-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -23,7 +23,7 @@ AC_DEFUN_ONCE([gl_STDLIB_H],
 # include <random.h>
 #endif
     ]], [_Exit aligned_alloc atoll canonicalize_file_name free
-    getloadavg getsubopt grantpt
+    getloadavg getprogname getsubopt grantpt
     initstate initstate_r mbtowc mkdtemp mkostemp mkostemps mkstemp mkstemps
     posix_memalign posix_openpt ptsname ptsname_r qsort_r
     random random_r reallocarray realpath rpmatch secure_getenv setenv
@@ -73,6 +73,7 @@ AC_DEFUN([gl_STDLIB_H_REQUIRE_DEFAULTS],
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_CANONICALIZE_FILE_NAME])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_FREE_POSIX])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_GETLOADAVG])
+    gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_GETPROGNAME])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_GETSUBOPT])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_GRANTPT])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MALLOC_GNU])
@@ -130,6 +131,7 @@ AC_DEFUN([gl_STDLIB_H_DEFAULTS],
   HAVE_DECL_FCVT=1;          AC_SUBST([HAVE_DECL_FCVT])
   HAVE_DECL_GCVT=1;          AC_SUBST([HAVE_DECL_GCVT])
   HAVE_DECL_GETLOADAVG=1;    AC_SUBST([HAVE_DECL_GETLOADAVG])
+  HAVE_GETPROGNAME=1;        AC_SUBST([HAVE_GETPROGNAME])
   HAVE_GETSUBOPT=1;          AC_SUBST([HAVE_GETSUBOPT])
   HAVE_GRANTPT=1;            AC_SUBST([HAVE_GRANTPT])
   HAVE_INITSTATE=1;          AC_SUBST([HAVE_INITSTATE])
@@ -166,17 +168,24 @@ AC_DEFUN([gl_STDLIB_H_DEFAULTS],
   HAVE_SYS_LOADAVG_H=0;      AC_SUBST([HAVE_SYS_LOADAVG_H])
   HAVE_UNLOCKPT=1;           AC_SUBST([HAVE_UNLOCKPT])
   HAVE_DECL_UNSETENV=1;      AC_SUBST([HAVE_DECL_UNSETENV])
+  REPLACE__EXIT=0;           AC_SUBST([REPLACE__EXIT])
   REPLACE_ALIGNED_ALLOC=0;   AC_SUBST([REPLACE_ALIGNED_ALLOC])
   REPLACE_CALLOC_FOR_CALLOC_GNU=0;    AC_SUBST([REPLACE_CALLOC_FOR_CALLOC_GNU])
   REPLACE_CALLOC_FOR_CALLOC_POSIX=0;  
AC_SUBST([REPLACE_CALLOC_FOR_CALLOC_POSIX])
   REPLACE_CANONICALIZE_FILE_NAME=0;  AC_SUBST([REPLACE_CANONICALIZE_FILE_NAME])
   REPLACE_FREE=0;            AC_SUBST([REPLACE_FREE])
+  REPLACE_GETLOADAVG=0;      AC_SUBST([REPLACE_GETLOADAVG])
+  REPLACE_GETPROGNAME=0;     AC_SUBST([REPLACE_GETPROGNAME])
+  REPLACE_GETSUBOPT=0;       AC_SUBST([REPLACE_GETSUBOPT])
   REPLACE_INITSTATE=0;       AC_SUBST([REPLACE_INITSTATE])
   REPLACE_MALLOC_FOR_MALLOC_GNU=0;    AC_SUBST([REPLACE_MALLOC_FOR_MALLOC_GNU])
   REPLACE_MALLOC_FOR_MALLOC_POSIX=0;  
AC_SUBST([REPLACE_MALLOC_FOR_MALLOC_POSIX])
   REPLACE_MBTOWC=0;          AC_SUBST([REPLACE_MBTOWC])
+  REPLACE_MKOSTEMP=0;        AC_SUBST([REPLACE_MKOSTEMP])
+  REPLACE_MKOSTEMPS=0;       AC_SUBST([REPLACE_MKOSTEMPS])
   REPLACE_MKSTEMP=0;         AC_SUBST([REPLACE_MKSTEMP])
   REPLACE_POSIX_MEMALIGN=0;  AC_SUBST([REPLACE_POSIX_MEMALIGN])
+  REPLACE_POSIX_OPENPT=0;    AC_SUBST([REPLACE_POSIX_OPENPT])
   REPLACE_PTSNAME=0;         AC_SUBST([REPLACE_PTSNAME])
   REPLACE_PTSNAME_R=0;       AC_SUBST([REPLACE_PTSNAME_R])
   REPLACE_PUTENV=0;          AC_SUBST([REPLACE_PUTENV])
diff --git a/m4/stpcpy.m4 b/m4/stpcpy.m4
index e8a76bc34f3..f3acbee7be9 100644
--- a/m4/stpcpy.m4
+++ b/m4/stpcpy.m4
@@ -1,4 +1,4 @@
-# stpcpy.m4 serial 9
+# stpcpy.m4 serial 11
 dnl Copyright (C) 2002, 2007, 2009-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -13,9 +13,12 @@ AC_DEFUN([gl_FUNC_STPCPY],
   AC_REQUIRE([AC_C_RESTRICT])
 
   AC_REQUIRE([gl_STRING_H_DEFAULTS])
-  AC_CHECK_FUNCS([stpcpy])
+  gl_CHECK_FUNCS_ANDROID([stpcpy], [[#include <string.h>]])
   if test $ac_cv_func_stpcpy = no; then
     HAVE_STPCPY=0
+    case "$gl_cv_onwards_func_stpcpy" in
+      future*) REPLACE_STPCPY=1 ;;
+    esac
   fi
 ])
 
diff --git a/m4/string_h.m4 b/m4/string_h.m4
index 5da3cc25291..7f51391cbff 100644
--- a/m4/string_h.m4
+++ b/m4/string_h.m4
@@ -5,7 +5,7 @@
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 35
+# serial 37
 
 # Written by Paul Eggert.
 
@@ -131,6 +131,8 @@ AC_DEFUN([gl_STRING_H_DEFAULTS],
   REPLACE_FFSLL=0;              AC_SUBST([REPLACE_FFSLL])
   REPLACE_MEMCHR=0;             AC_SUBST([REPLACE_MEMCHR])
   REPLACE_MEMMEM=0;             AC_SUBST([REPLACE_MEMMEM])
+  REPLACE_MEMPCPY=0;            AC_SUBST([REPLACE_MEMPCPY])
+  REPLACE_STPCPY=0;             AC_SUBST([REPLACE_STPCPY])
   REPLACE_STPNCPY=0;            AC_SUBST([REPLACE_STPNCPY])
   REPLACE_STRCHRNUL=0;          AC_SUBST([REPLACE_STRCHRNUL])
   REPLACE_STRDUP=0;             AC_SUBST([REPLACE_STRDUP])
diff --git a/m4/time_h.m4 b/m4/time_h.m4
index f6bf3a4f30e..b74870c3d0e 100644
--- a/m4/time_h.m4
+++ b/m4/time_h.m4
@@ -2,7 +2,7 @@
 
 # Copyright (C) 2000-2001, 2003-2007, 2009-2023 Free Software Foundation, Inc.
 
-# serial 20
+# serial 21
 
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -170,6 +170,7 @@ AC_DEFUN([gl_TIME_H_DEFAULTS],
   REPLACE_NANOSLEEP=GNULIB_PORTCHECK;    AC_SUBST([REPLACE_NANOSLEEP])
   REPLACE_STRFTIME=GNULIB_PORTCHECK;     AC_SUBST([REPLACE_STRFTIME])
   REPLACE_TIMEGM=GNULIB_PORTCHECK;       AC_SUBST([REPLACE_TIMEGM])
+  REPLACE_TIMESPEC_GET=GNULIB_PORTCHECK; AC_SUBST([REPLACE_TIMESPEC_GET])
   REPLACE_TZSET=GNULIB_PORTCHECK;        AC_SUBST([REPLACE_TZSET])
 
   dnl Hack so that the time module doesn't depend on the sys_time module.
diff --git a/m4/timegm.m4 b/m4/timegm.m4
index 6079f1a39c8..8ab265e65fe 100644
--- a/m4/timegm.m4
+++ b/m4/timegm.m4
@@ -1,4 +1,4 @@
-# timegm.m4 serial 13
+# timegm.m4 serial 15
 dnl Copyright (C) 2003, 2007, 2009-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -9,7 +9,7 @@ AC_DEFUN([gl_FUNC_TIMEGM],
   AC_REQUIRE([gl_TIME_H_DEFAULTS])
   AC_REQUIRE([gl_FUNC_MKTIME_WORKS])
   REPLACE_TIMEGM=0
-  AC_CHECK_FUNCS_ONCE([timegm])
+  gl_CHECK_FUNCS_ANDROID([timegm], [[#include <time.h>]])
   if test $ac_cv_func_timegm = yes; then
     if test "$gl_cv_func_working_mktime" != yes; then
       # Assume that timegm is buggy if mktime is.
@@ -17,6 +17,9 @@ AC_DEFUN([gl_FUNC_TIMEGM],
     fi
   else
     HAVE_TIMEGM=0
+    case "$gl_cv_onwards_func_timegm" in
+      future*) REPLACE_TIMEGM=1 ;;
+    esac
   fi
 ])
 
diff --git a/m4/unistd_h.m4 b/m4/unistd_h.m4
index f4384027e37..1c96158155a 100644
--- a/m4/unistd_h.m4
+++ b/m4/unistd_h.m4
@@ -1,4 +1,4 @@
-# unistd_h.m4 serial 90
+# unistd_h.m4 serial 94
 dnl Copyright (C) 2006-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -225,6 +225,7 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS],
   REPLACE_COPY_FILE_RANGE=0;         AC_SUBST([REPLACE_COPY_FILE_RANGE])
   REPLACE_DUP=0;                     AC_SUBST([REPLACE_DUP])
   REPLACE_DUP2=0;                    AC_SUBST([REPLACE_DUP2])
+  REPLACE_DUP3=0;                    AC_SUBST([REPLACE_DUP3])
   REPLACE_EXECL=0;                   AC_SUBST([REPLACE_EXECL])
   REPLACE_EXECLE=0;                  AC_SUBST([REPLACE_EXECLE])
   REPLACE_EXECLP=0;                  AC_SUBST([REPLACE_EXECLP])
@@ -234,10 +235,12 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS],
   REPLACE_EXECVPE=0;                 AC_SUBST([REPLACE_EXECVPE])
   REPLACE_FACCESSAT=0;               AC_SUBST([REPLACE_FACCESSAT])
   REPLACE_FCHOWNAT=0;                AC_SUBST([REPLACE_FCHOWNAT])
+  REPLACE_FDATASYNC=0;               AC_SUBST([REPLACE_FDATASYNC])
   REPLACE_FTRUNCATE=0;               AC_SUBST([REPLACE_FTRUNCATE])
   REPLACE_GETCWD=0;                  AC_SUBST([REPLACE_GETCWD])
   REPLACE_GETDOMAINNAME=0;           AC_SUBST([REPLACE_GETDOMAINNAME])
   REPLACE_GETDTABLESIZE=0;           AC_SUBST([REPLACE_GETDTABLESIZE])
+  REPLACE_GETENTROPY=0;              AC_SUBST([REPLACE_GETENTROPY])
   REPLACE_GETLOGIN_R=0;              AC_SUBST([REPLACE_GETLOGIN_R])
   REPLACE_GETGROUPS=0;               AC_SUBST([REPLACE_GETGROUPS])
   REPLACE_GETPAGESIZE=0;             AC_SUBST([REPLACE_GETPAGESIZE])
@@ -248,12 +251,14 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS],
   REPLACE_LINK=0;                    AC_SUBST([REPLACE_LINK])
   REPLACE_LINKAT=0;                  AC_SUBST([REPLACE_LINKAT])
   REPLACE_LSEEK=0;                   AC_SUBST([REPLACE_LSEEK])
+  REPLACE_PIPE2=0;                   AC_SUBST([REPLACE_PIPE2])
   REPLACE_PREAD=0;                   AC_SUBST([REPLACE_PREAD])
   REPLACE_PWRITE=0;                  AC_SUBST([REPLACE_PWRITE])
   REPLACE_READ=0;                    AC_SUBST([REPLACE_READ])
   REPLACE_READLINK=0;                AC_SUBST([REPLACE_READLINK])
   REPLACE_READLINKAT=0;              AC_SUBST([REPLACE_READLINKAT])
   REPLACE_RMDIR=0;                   AC_SUBST([REPLACE_RMDIR])
+  REPLACE_SETHOSTNAME=0;             AC_SUBST([REPLACE_SETHOSTNAME])
   REPLACE_SLEEP=0;                   AC_SUBST([REPLACE_SLEEP])
   REPLACE_SYMLINK=0;                 AC_SUBST([REPLACE_SYMLINK])
   REPLACE_SYMLINKAT=0;               AC_SUBST([REPLACE_SYMLINKAT])
diff --git a/m4/utimens.m4 b/m4/utimens.m4
index c5d9b69e6f5..5f8606167a6 100644
--- a/m4/utimens.m4
+++ b/m4/utimens.m4
@@ -3,7 +3,7 @@ dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
 dnl with or without modifications, as long as this notice is preserved.
 
-dnl serial 12
+dnl serial 15
 
 AC_DEFUN([gl_UTIMENS],
 [
@@ -11,9 +11,11 @@ AC_DEFUN([gl_UTIMENS],
   AC_REQUIRE([gl_FUNC_UTIMES])
   AC_REQUIRE([gl_CHECK_TYPE_STRUCT_TIMESPEC])
   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
-  AC_CHECK_FUNCS_ONCE([futimens utimensat lutimes])
   gl_CHECK_FUNCS_ANDROID([futimes], [[#include <sys/time.h>]])
   gl_CHECK_FUNCS_ANDROID([futimesat], [[#include <sys/time.h>]])
+  gl_CHECK_FUNCS_ANDROID([lutimes], [[#include <sys/time.h>]])
+  gl_CHECK_FUNCS_ANDROID([futimens], [[#include <sys/stat.h>]])
+  gl_CHECK_FUNCS_ANDROID([utimensat], [[#include <sys/stat.h>]])
 
   if test $ac_cv_func_futimens = no && test $ac_cv_func_futimesat = yes; then
     dnl FreeBSD 8.0-rc2 mishandles futimesat(fd,NULL,time).  It is not
diff --git a/m4/utimensat.m4 b/m4/utimensat.m4
index dd210fc989a..1a670bb7b78 100644
--- a/m4/utimensat.m4
+++ b/m4/utimensat.m4
@@ -1,4 +1,4 @@
-# serial 9
+# serial 11
 # See if we need to provide utimensat replacement.
 
 dnl Copyright (C) 2009-2023 Free Software Foundation, Inc.
@@ -13,9 +13,12 @@ AC_DEFUN([gl_FUNC_UTIMENSAT],
   AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS])
   AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
-  AC_CHECK_FUNCS_ONCE([utimensat])
+  gl_CHECK_FUNCS_ANDROID([utimensat], [[#include <sys/stat.h>]])
   if test $ac_cv_func_utimensat = no; then
     HAVE_UTIMENSAT=0
+    case "$gl_cv_onwards_func_utimensat" in
+      future*) REPLACE_UTIMENSAT=1 ;;
+    esac
   else
     AC_CACHE_CHECK([whether utimensat works],
       [gl_cv_func_utimensat_works],
diff --git a/nt/INSTALL.W64 b/nt/INSTALL.W64
index fa576fb4d7f..fe5f74e3209 100644
--- a/nt/INSTALL.W64
+++ b/nt/INSTALL.W64
@@ -115,7 +115,7 @@ put the Emacs source into C:\emacs\emacs-master:
 
   mkdir /c/emacs
   cd /c/emacs
-  git clone git://git.sv.gnu.org/emacs.git emacs-master
+  git clone https://git.savannah.gnu.org/git/emacs.git emacs-master
 
 This will produce the development sources, i.e. the master branch of
 the Emacs Git repository, in the directory C:\emacs\emacs-master.
diff --git a/src/comp.c b/src/comp.c
index f539a7c368d..21d158257ec 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -614,7 +614,7 @@ load_gccjit_if_necessary (bool mandatory)
 #define SETJMP_NAME SETJMP
 
 /* Max number function importable by native compiled code.  */
-#define F_RELOC_MAX_SIZE 1500
+#define F_RELOC_MAX_SIZE 1600
 
 typedef struct {
   void *link_table[F_RELOC_MAX_SIZE];
@@ -8636,6 +8636,3 @@ file -> CU.  */);
 
   defsubr (&Snative_comp_available_p);
 }
-/* Local Variables: */
-/* c-file-offsets: ((arglist-intro . +)) */
-/* End: */
diff --git a/src/dispnew.c b/src/dispnew.c
index 8fde522f77d..43306043a0c 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -5009,6 +5009,10 @@ update_frame_1 (struct frame *f, bool force_p, bool 
inhibit_id_p,
            }
          while (row > top && col == 0);
 
+         /* We exit the loop with COL at the glyph _after_ the last one.  */
+         if (col > 0)
+           col--;
+
          /* Make sure COL is not out of range.  */
          if (col >= FRAME_CURSOR_X_LIMIT (f))
            {
diff --git a/src/floatfns.c b/src/floatfns.c
index 1d891ef3ce1..13f0ca3e129 100644
--- a/src/floatfns.c
+++ b/src/floatfns.c
@@ -27,19 +27,22 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
    frexp, ldexp, log, log10 [via (log X 10)], *modf, pow, sin, *sinh,
    sqrt, tan, *tanh.
 
-   C99 and C11 require the following math.h functions in addition to
+   C99, C11 and C17 require the following math.h functions in addition to
    the C89 functions.  Of these, Emacs currently exports only the
    starred ones to Lisp, since we haven't found a use for the others.
    Also, it uses the ones marked "+" internally:
    acosh, atanh, cbrt, copysign (implemented by signbit), erf, erfc,
    exp2, expm1, fdim, fma, fmax, fmin, fpclassify, hypot, +ilogb,
-   isfinite, isgreater, isgreaterequal, isinf, isless, islessequal,
+   +isfinite, isgreater, isgreaterequal, +isinf, isless, islessequal,
    islessgreater, *isnan, isnormal, isunordered, lgamma, log1p, *log2
    [via (log X 2)], logb (approximately; implemented by frexp),
    +lrint/llrint, +lround/llround, nan, nearbyint, nextafter,
    nexttoward, remainder, remquo, *rint, round, scalbln, +scalbn,
    +signbit, tgamma, *trunc.
 
+   C23 requires many more math.h functions.  Emacs does not yet export
+   or use them.
+
    The C standard also requires functions for float and long double
    that are not listed above.  Of these functions, Emacs uses only the
    following internally: fabsf, powf, sprintf.
diff --git a/src/insdel.c b/src/insdel.c
index 0e1e98664b3..e459d0cfa17 100644
--- a/src/insdel.c
+++ b/src/insdel.c
@@ -1101,6 +1101,10 @@ insert_from_gap_1 (ptrdiff_t nchars, ptrdiff_t nbytes, 
bool text_at_gap_tail)
   eassert (NILP (BVAR (current_buffer, enable_multibyte_characters))
            ? nchars == nbytes : nchars <= nbytes);
 
+#ifdef HAVE_TREE_SITTER
+  ptrdiff_t ins_bytepos = GPT_BYTE;
+#endif
+
   GAP_SIZE -= nbytes;
   if (! text_at_gap_tail)
     {
@@ -1115,6 +1119,12 @@ insert_from_gap_1 (ptrdiff_t nchars, ptrdiff_t nbytes, 
bool text_at_gap_tail)
   /* Put an anchor to ensure multi-byte form ends at gap.  */
   if (GAP_SIZE > 0) *(GPT_ADDR) = 0;
   eassert (GPT <= GPT_BYTE);
+
+#ifdef HAVE_TREE_SITTER
+  eassert (nbytes >= 0);
+  eassert (ins_bytepos >= 0);
+  treesit_record_change (ins_bytepos, ins_bytepos, ins_bytepos + nbytes);
+#endif
 }
 
 /* Insert a sequence of NCHARS chars which occupy NBYTES bytes
@@ -1150,12 +1160,6 @@ insert_from_gap (ptrdiff_t nchars, ptrdiff_t nbytes, 
bool text_at_gap_tail)
                                   current_buffer, 0);
     }
 
-#ifdef HAVE_TREE_SITTER
-  eassert (nbytes >= 0);
-  eassert (ins_bytepos >= 0);
-  treesit_record_change (ins_bytepos, ins_bytepos, ins_bytepos + nbytes);
-#endif
-
   if (ins_charpos < PT)
     adjust_point (nchars, nbytes);
 
@@ -1191,6 +1195,9 @@ insert_from_buffer (struct buffer *buf,
 #endif
 }
 
+/* NOTE: If we ever make insert_from_buffer_1 public, make sure to
+   move the call to treesit_record_change into it.  */
+
 static void
 insert_from_buffer_1 (struct buffer *buf,
                      ptrdiff_t from, ptrdiff_t nchars, bool inherit)
diff --git a/src/lisp.h b/src/lisp.h
index e860bf4594f..b010ffa1397 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -274,7 +274,7 @@ DEFINE_GDB_SYMBOL_END (VALMASK)
    emacs_align_type union in alloc.c.
 
    Although these macros are reasonably portable, they are not
-   guaranteed on non-GCC platforms, as C11 does not require support
+   guaranteed on non-GCC platforms, as the C standard does not require support
    for alignment to GCALIGNMENT and older compilers may ignore
    alignment requests.  For any type T where garbage collection
    requires alignment, use verify (GCALIGNED (T)) to verify the
@@ -3015,9 +3015,10 @@ XFLOAT_DATA (Lisp_Object f)
 /* Most hosts nowadays use IEEE floating point, so they use IEC 60559
    representations, have infinities and NaNs, and do not trap on
    exceptions.  Define IEEE_FLOATING_POINT to 1 if this host is one of the
-   typical ones.  The C11 macro __STDC_IEC_559__ is close to what is
+   typical ones.  The C23 macro __STDC_IEC_60559_BFP__ (or its
+   obsolescent C11 counterpart __STDC_IEC_559__) is close to what is
    wanted here, but is not quite right because Emacs does not require
-   all the features of C11 Annex F (and does not require C11 at all,
+   all the features of C23 Annex F (and does not require C11 or later,
    for that matter).  */
 
 #define IEEE_FLOATING_POINT (FLT_RADIX == 2 && FLT_MANT_DIG == 24 \
@@ -4875,6 +4876,9 @@ extern ptrdiff_t find_newline_no_quit (ptrdiff_t, 
ptrdiff_t,
                                       ptrdiff_t, ptrdiff_t *);
 extern ptrdiff_t find_before_next_newline (ptrdiff_t, ptrdiff_t,
                                           ptrdiff_t, ptrdiff_t *);
+extern EMACS_INT search_buffer (Lisp_Object, ptrdiff_t, ptrdiff_t,
+                               ptrdiff_t, ptrdiff_t, EMACS_INT,
+                               int, Lisp_Object, Lisp_Object, bool);
 extern void syms_of_search (void);
 extern void clear_regexp_cache (void);
 
diff --git a/src/search.c b/src/search.c
index dbc5a83946f..0bb52c03eef 100644
--- a/src/search.c
+++ b/src/search.c
@@ -68,9 +68,6 @@ static EMACS_INT simple_search (EMACS_INT, unsigned char *, 
ptrdiff_t,
 static EMACS_INT boyer_moore (EMACS_INT, unsigned char *, ptrdiff_t,
                               Lisp_Object, Lisp_Object, ptrdiff_t,
                               ptrdiff_t, int);
-static EMACS_INT search_buffer (Lisp_Object, ptrdiff_t, ptrdiff_t,
-                                ptrdiff_t, ptrdiff_t, EMACS_INT, int,
-                                Lisp_Object, Lisp_Object, bool);
 
 Lisp_Object re_match_object;
 
@@ -1510,7 +1507,7 @@ search_buffer_non_re (Lisp_Object string, ptrdiff_t pos,
   return result;
 }
 
-static EMACS_INT
+EMACS_INT
 search_buffer (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
               ptrdiff_t lim, ptrdiff_t lim_byte, EMACS_INT n,
               int RE, Lisp_Object trt, Lisp_Object inverse_trt, bool posix)
diff --git a/src/sqlite.c b/src/sqlite.c
index c96841e63f9..0361514766a 100644
--- a/src/sqlite.c
+++ b/src/sqlite.c
@@ -399,7 +399,7 @@ row_to_value (sqlite3_stmt *stmt)
   int len = sqlite3_column_count (stmt);
   Lisp_Object values = Qnil;
 
-  for (int i = 0; i < len; ++i)
+  for (int i = len - 1; i >= 0; i--)
     {
       Lisp_Object v = Qnil;
 
@@ -434,7 +434,7 @@ row_to_value (sqlite3_stmt *stmt)
       values = Fcons (v, values);
     }
 
-  return Fnreverse (values);
+  return values;
 }
 
 static Lisp_Object
@@ -718,11 +718,15 @@ Only modules on Emacs' list of allowed modules can be 
loaded.  */)
 #endif /* HAVE_SQLITE3_LOAD_EXTENSION */
 
 DEFUN ("sqlite-next", Fsqlite_next, Ssqlite_next, 1, 1, 0,
-       doc: /* Return the next result set from SET.  */)
+       doc: /* Return the next result set from SET.
+Return nil when the statement has finished executing successfully.  */)
   (Lisp_Object set)
 {
   check_sqlite (set, true);
 
+  if (XSQLITE (set)->eof)
+    return Qnil;
+
   int ret = sqlite3_step (XSQLITE (set)->stmt);
   if (ret != SQLITE_ROW && ret != SQLITE_OK && ret != SQLITE_DONE)
     xsignal1 (Qsqlite_error, build_string (sqlite3_errmsg (XSQLITE 
(set)->db)));
diff --git a/src/treesit.c b/src/treesit.c
index 917db582676..8e772523cc7 100644
--- a/src/treesit.c
+++ b/src/treesit.c
@@ -72,6 +72,7 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 #undef ts_query_cursor_set_byte_range
 #undef ts_query_delete
 #undef ts_query_new
+#undef ts_query_pattern_count
 #undef ts_query_predicates_for_pattern
 #undef ts_query_string_value_for_id
 #undef ts_set_allocator
@@ -135,6 +136,7 @@ DEF_DLL_FN (void, ts_query_cursor_set_byte_range,
 DEF_DLL_FN (void, ts_query_delete, (TSQuery *));
 DEF_DLL_FN (TSQuery *, ts_query_new,
            (const TSLanguage *, const char *, uint32_t, uint32_t *, 
TSQueryError *));
+DEF_DLL_FN (uint32_t, ts_query_pattern_count, (const TSQuery *));
 DEF_DLL_FN (const TSQueryPredicateStep *, ts_query_predicates_for_pattern,
            ( const TSQuery *, uint32_t, uint32_t *));
 DEF_DLL_FN (const char *, ts_query_string_value_for_id,
@@ -200,6 +202,7 @@ init_treesit_functions (void)
   LOAD_DLL_FN (library, ts_query_cursor_set_byte_range);
   LOAD_DLL_FN (library, ts_query_delete);
   LOAD_DLL_FN (library, ts_query_new);
+  LOAD_DLL_FN (library, ts_query_pattern_count);
   LOAD_DLL_FN (library, ts_query_predicates_for_pattern);
   LOAD_DLL_FN (library, ts_query_string_value_for_id);
   LOAD_DLL_FN (library, ts_set_allocator);
@@ -256,6 +259,7 @@ init_treesit_functions (void)
 #define ts_query_cursor_set_byte_range fn_ts_query_cursor_set_byte_range
 #define ts_query_delete fn_ts_query_delete
 #define ts_query_new fn_ts_query_new
+#define ts_query_pattern_count fn_ts_query_pattern_count
 #define ts_query_predicates_for_pattern fn_ts_query_predicates_for_pattern
 #define ts_query_string_value_for_id fn_ts_query_string_value_for_id
 #define ts_set_allocator fn_ts_set_allocator
@@ -2466,13 +2470,42 @@ treesit_predicate_match (Lisp_Object args, struct 
capture_range captures)
              build_string ("The second argument to `match' should "
                            "be a capture name, not a string"));
 
-  Lisp_Object text = treesit_predicate_capture_name_to_text (capture_name,
+  Lisp_Object node = treesit_predicate_capture_name_to_node (capture_name,
                                                             captures);
 
-  if (fast_string_match (regexp, text) >= 0)
-    return true;
-  else
-    return false;
+  struct buffer *old_buffer = current_buffer;
+  struct buffer *buffer = XBUFFER (XTS_PARSER (XTS_NODE 
(node)->parser)->buffer);
+  set_buffer_internal (buffer);
+
+  TSNode treesit_node = XTS_NODE (node)->node;
+  ptrdiff_t visible_beg = XTS_PARSER (XTS_NODE (node)->parser)->visible_beg;
+  uint32_t start_byte_offset = ts_node_start_byte (treesit_node);
+  uint32_t end_byte_offset = ts_node_end_byte (treesit_node);
+  ptrdiff_t start_byte = visible_beg + start_byte_offset;
+  ptrdiff_t end_byte = visible_beg + end_byte_offset;
+  ptrdiff_t start_pos = BYTE_TO_CHAR (start_byte);
+  ptrdiff_t end_pos = BYTE_TO_CHAR (end_byte);
+  ptrdiff_t old_begv = BEGV;
+  ptrdiff_t old_begv_byte = BEGV_BYTE;
+  ptrdiff_t old_zv = ZV;
+  ptrdiff_t old_zv_byte = ZV_BYTE;
+
+  BEGV = start_pos;
+  BEGV_BYTE = start_byte;
+  ZV = end_pos;
+  ZV_BYTE = end_byte;
+
+  ptrdiff_t val = search_buffer (regexp, start_pos, start_byte,
+                                end_pos, end_byte, 1, 1, Qnil, Qnil, false);
+
+  BEGV = old_begv;
+  BEGV_BYTE = old_begv_byte;
+  ZV = old_zv;
+  ZV_BYTE = old_zv_byte;
+
+  set_buffer_internal (old_buffer);
+
+  return (val > 0);
 }
 
 /* Handles predicate (#pred FN ARG...).  Return true if FN returns
@@ -2720,8 +2753,10 @@ the query.  */)
      every for loop and nconc it to RESULT every time.  That is indeed
      the initial implementation in which Yoav found nconc being the
      bottleneck (98.4% of the running time spent on nconc).  */
+  uint32_t patterns_count = ts_query_pattern_count (treesit_query);
   Lisp_Object result = Qnil;
   Lisp_Object prev_result = result;
+  Lisp_Object predicates_table = make_vector (patterns_count, Qt);
   while (ts_query_cursor_next_match (cursor, &match))
     {
       /* Record the checkpoint that we may roll back to.  */
@@ -2750,9 +2785,13 @@ the query.  */)
          result = Fcons (cap, result);
        }
       /* Get predicates.  */
-      Lisp_Object predicates
-       = treesit_predicates_for_pattern (treesit_query,
-                                         match.pattern_index);
+      Lisp_Object predicates = AREF (predicates_table, match.pattern_index);
+      if (EQ (predicates, Qt))
+       {
+         predicates = treesit_predicates_for_pattern (treesit_query,
+                                                      match.pattern_index);
+         ASET (predicates_table, match.pattern_index, predicates);
+       }
 
       /* captures_lisp = Fnreverse (captures_lisp); */
       struct capture_range captures_range = { result, prev_result };
@@ -3312,6 +3351,68 @@ a regexp.  */)
     return parent;
 }
 
+DEFUN ("treesit-subtree-stat",
+       Ftreesit_subtree_stat,
+       Streesit_subtree_stat, 1, 1, 0,
+       doc: /* Return information about the subtree of NODE.
+
+Return a list (MAX-DEPTH MAX-WIDTH COUNT), where MAX-DEPTH is the
+maximum depth of the subtree, MAX-WIDTH is the maximum number of
+direct children of nodes in the subtree, and COUNT is the number of
+nodes in the subtree, including NODE.  */)
+  (Lisp_Object node)
+{
+  /* Having a limit on the depth to traverse doesn't have much impact
+     on the time it takes, so I left that out.  */
+  CHECK_TS_NODE (node);
+
+  treesit_initialize ();
+
+  TSTreeCursor cursor = ts_tree_cursor_new (XTS_NODE (node)->node);
+  ptrdiff_t max_depth = 1;
+  ptrdiff_t max_width = 0;
+  ptrdiff_t count = 0;
+  ptrdiff_t current_depth = 0;
+
+  /* Traverse the subtree depth-first.  */
+  while (true)
+    {
+      count++;
+
+      /* Go down depth-first.  */
+      while (ts_tree_cursor_goto_first_child (&cursor))
+       {
+         current_depth++;
+         count++;
+         /* While we're at here, measure the number of siblings.  */
+         ptrdiff_t width_count = 1;
+         while (ts_tree_cursor_goto_next_sibling (&cursor))
+           width_count++;
+         max_width = max (max_width, width_count);
+         /* Go back to the first sibling.  */
+         treesit_assume_true (ts_tree_cursor_goto_parent (&cursor));
+         treesit_assume_true (ts_tree_cursor_goto_first_child (&cursor));
+       }
+      max_depth = max (max_depth, current_depth);
+
+      /* Go to next sibling.  If there is no next sibling, go to
+         parent's next sibling, and so on.  If there is no more
+         parent, we've traversed the whole subtree, stop.  */
+      while (!ts_tree_cursor_goto_next_sibling (&cursor))
+       {
+         if (ts_tree_cursor_goto_parent (&cursor))
+           current_depth--;
+         else
+           {
+             ts_tree_cursor_delete (&cursor);
+             return list3 (make_fixnum (max_depth),
+                           make_fixnum (max_width),
+                           make_fixnum (count));
+           }
+       }
+    }
+}
+
 #endif /* HAVE_TREE_SITTER */
 
 DEFUN ("treesit-available-p", Ftreesit_available_p,
@@ -3511,6 +3612,7 @@ then in the system default locations for dynamic 
libraries, in that order.  */);
   defsubr (&Streesit_search_subtree);
   defsubr (&Streesit_search_forward);
   defsubr (&Streesit_induce_sparse_tree);
+  defsubr (&Streesit_subtree_stat);
 #endif /* HAVE_TREE_SITTER */
   defsubr (&Streesit_available_p);
 }
diff --git a/src/xdisp.c b/src/xdisp.c
index aeeca2674ea..ed870004b43 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -12448,7 +12448,7 @@ display_echo_area (struct window *w)
      reset the echo_area_buffer in question to nil at the end because
      with_echo_area_buffer will set it to an empty buffer.  */
   bool i = display_last_displayed_message_p;
-  /* According to the C99, C11 and C++11 standards, the integral value
+  /* According to the C standard, the integral value
      of a "bool" is always 0 or 1, so this array access is safe here,
      if oddly typed. */
   no_message_p = NILP (echo_area_buffer[i]);
diff --git a/src/xfaces.c b/src/xfaces.c
index 35b79154805..62d7823f308 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -2780,8 +2780,7 @@ merge_face_ref (struct window *w,
              else if (EQ (keyword, QCstipple))
                {
 #if defined (HAVE_WINDOW_SYSTEM)
-                 Lisp_Object pixmap_p = Fbitmap_spec_p (value);
-                 if (!NILP (pixmap_p))
+                 if (NILP (value) || !NILP (Fbitmap_spec_p (value)))
                    to[LFACE_STIPPLE_INDEX] = value;
                  else
                    err = true;
diff --git a/test/lisp/emacs-lisp/nadvice-tests.el 
b/test/lisp/emacs-lisp/nadvice-tests.el
index 748d42f2120..987483f00b1 100644
--- a/test/lisp/emacs-lisp/nadvice-tests.el
+++ b/test/lisp/emacs-lisp/nadvice-tests.el
@@ -213,8 +213,16 @@ function being an around advice."
     (should (equal (cl-prin1-to-string (car x))
                    "#f(advice first :before #f(advice car :after cdr))"))))
 
-;; Local Variables:
-;; no-byte-compile: t
-;; End:
+(ert-deftest advice-test-bug61179 ()
+  (let* ((magic 42)
+         (ad (lambda (&rest _)
+               (interactive (lambda (is)
+                              (cons magic (advice-eval-interactive-spec is))))
+               nil))
+         (sym (make-symbol "adtest")))
+    (defalias sym (lambda (&rest args) (interactive (list 'main)) args))
+    (should (equal (call-interactively sym) '(main)))
+    (advice-add sym :before ad)
+    (should (equal (call-interactively sym) '(42 main)))))
 
 ;;; nadvice-tests.el ends here
diff --git a/test/lisp/eshell/em-cmpl-tests.el 
b/test/lisp/eshell/em-cmpl-tests.el
new file mode 100644
index 00000000000..12a156fbb38
--- /dev/null
+++ b/test/lisp/eshell/em-cmpl-tests.el
@@ -0,0 +1,208 @@
+;;; em-cmpl-tests.el --- em-cmpl test suite  -*- lexical-binding:t -*-
+
+;; Copyright (C) 2023 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Tests for Eshell's interactive completion.
+
+;;; Code:
+
+(require 'ert)
+(require 'eshell)
+(require 'em-cmpl)
+(require 'em-dirs)
+(require 'em-hist)
+(require 'em-tramp)
+(require 'em-unix)
+
+(require 'eshell-tests-helpers
+         (expand-file-name "eshell-tests-helpers"
+                           (file-name-directory (or load-file-name
+                                                    default-directory))))
+
+(defvar eshell-test-value nil)
+
+(defun eshell-insert-and-complete (input)
+  "Insert INPUT and invoke completion, returning the result."
+  (insert input)
+  (completion-at-point)
+  (eshell-get-old-input))
+
+(defun eshell-arguments-equal (actual expected)
+  "Return t if ACTUAL and EXPECTED are equal, including properties of strings.
+ACTUAL and EXPECTED should both be lists of strings."
+  (when (length= actual (length expected))
+    (catch 'not-equal
+      (cl-mapc (lambda (i j)
+                 (unless (equal-including-properties i j)
+                   (throw 'not-equal nil)))
+               actual expected)
+      t)))
+
+(defun eshell-arguments-equal--equal-explainer (actual expected)
+  "Explain the result of `eshell-arguments-equal'."
+  `(nonequal-result
+    (actual ,actual)
+    (expected ,expected)))
+
+(put 'eshell-arguments-equal 'ert-explainer
+     #'eshell-arguments-equal--equal-explainer)
+
+;;; Tests:
+
+(ert-deftest em-cmpl-test/parse-arguments/pipeline ()
+  "Test that parsing arguments for completion discards earlier commands."
+  (with-temp-eshell
+   (let ((eshell-test-value '("foo" "bar")))
+     (insert "echo hi | cat")
+     (should (eshell-arguments-equal
+              (car (eshell-complete-parse-arguments))
+              '("cat"))))))
+
+(ert-deftest em-cmpl-test/parse-arguments/multiple-dots ()
+  "Test parsing arguments with multiple dots like \".../\"."
+  (with-temp-eshell
+   (insert "echo .../file.txt")
+   (should (eshell-arguments-equal
+            (car (eshell-complete-parse-arguments))
+            `("echo" ,(propertize "../../file.txt"
+                                  'pcomplete-arg-value
+                                  ".../file.txt"))))))
+
+(ert-deftest em-cmpl-test/parse-arguments/variable/numeric ()
+  "Test parsing arguments with a numeric variable interpolation."
+  (with-temp-eshell
+   (let ((eshell-test-value 42))
+     (insert "echo $eshell-test-value")
+     (should (eshell-arguments-equal
+              (car (eshell-complete-parse-arguments))
+              `("echo" ,(propertize "42" 'pcomplete-arg-value 42)))))))
+
+(ert-deftest em-cmpl-test/parse-arguments/variable/nil ()
+  "Test parsing arguments with a nil variable interpolation."
+  (with-temp-eshell
+   (let ((eshell-test-value nil))
+     (insert "echo $eshell-test-value")
+     (should (eshell-arguments-equal
+              (car (eshell-complete-parse-arguments))
+              `("echo" ,(propertize "" 'pcomplete-arg-value nil)))))))
+
+(ert-deftest em-cmpl-test/parse-arguments/variable/list ()
+  "Test parsing arguments with a list variable interpolation."
+  (with-temp-eshell
+   (let ((eshell-test-value '("foo" "bar")))
+     (insert "echo $eshell-test-value")
+     (should (eshell-arguments-equal
+              (car (eshell-complete-parse-arguments))
+              `("echo" ,(propertize "(\"foo\" \"bar\")"
+                                    'pcomplete-arg-value
+                                    eshell-test-value)))))))
+
+(ert-deftest em-cmpl-test/parse-arguments/variable/splice ()
+  "Test parsing arguments with a spliced variable interpolation."
+  (with-temp-eshell
+   (let ((eshell-test-value '("foo" "bar")))
+     (insert "echo $@eshell-test-value")
+     (should (eshell-arguments-equal
+              (car (eshell-complete-parse-arguments))
+              '("echo" "foo" "bar"))))))
+
+(ert-deftest em-cmpl-test/file-completion/unique ()
+  "Test completion of file names when there's a unique result."
+  (with-temp-eshell
+   (ert-with-temp-directory default-directory
+     (write-region nil nil (expand-file-name "file.txt"))
+     (should (equal (eshell-insert-and-complete "echo fi")
+                    "echo file.txt ")))))
+
+(ert-deftest em-cmpl-test/file-completion/non-unique ()
+  "Test completion of file names when there are multiple results."
+  (with-temp-eshell
+   (ert-with-temp-directory default-directory
+     (write-region nil nil (expand-file-name "file.txt"))
+     (write-region nil nil (expand-file-name "file.el"))
+     (should (equal (eshell-insert-and-complete "echo fi")
+                    "echo file."))
+     ;; Now try completing again.
+     (let ((minibuffer-message-timeout 0)
+           (inhibit-message t))
+       (completion-at-point))
+     ;; FIXME: We can't use `current-message' here.
+     (with-current-buffer (messages-buffer)
+       (save-excursion
+         (goto-char (point-max))
+         (forward-line -1)
+         (should (looking-at "Complete, but not unique")))))))
+
+(ert-deftest em-cmpl-test/file-completion/after-list ()
+  "Test completion of file names after previous list arguments.
+See bug#59956."
+  (with-temp-eshell
+   (ert-with-temp-directory default-directory
+     (write-region nil nil (expand-file-name "file.txt"))
+     (should (equal (eshell-insert-and-complete "echo (list 1 2) fi")
+                    "echo (list 1 2) file.txt ")))))
+
+(ert-deftest em-cmpl-test/lisp-symbol-completion ()
+  "Test completion of Lisp forms like \"#'symbol\" and \"`symbol\".
+See <lisp/eshell/esh-cmd.el>."
+  (with-temp-eshell
+   (should (equal (eshell-insert-and-complete "echo #'system-nam")
+                  "echo #'system-name ")))
+  (with-temp-eshell
+   (should (equal (eshell-insert-and-complete "echo `system-nam")
+                  "echo `system-name "))))
+
+(ert-deftest em-cmpl-test/lisp-function-completion ()
+  "Test completion of Lisp forms like \"(func)\".
+See <lisp/eshell/esh-cmd.el>."
+  (with-temp-eshell
+   (should (equal (eshell-insert-and-complete "echo (eshell/ech")
+                  "echo (eshell/echo"))))
+
+(ert-deftest em-cmpl-test/variable-ref-completion ()
+  "Test completion of variable references like \"$var\".
+See <lisp/eshell/esh-var.el>."
+  (with-temp-eshell
+   (should (equal (eshell-insert-and-complete "echo $system-nam")
+                  "echo $system-name "))))
+
+(ert-deftest em-cmpl-test/variable-assign-completion ()
+  "Test completion of variable assignments like \"var=value\".
+See <lisp/eshell/esh-var.el>."
+  (with-temp-eshell
+   (ert-with-temp-directory default-directory
+     (write-region nil nil (expand-file-name "file.txt"))
+     (should (equal (eshell-insert-and-complete "VAR=f")
+                    "VAR=file.txt ")))))
+
+(ert-deftest em-cmpl-test/user-ref-completion ()
+  "Test completeion of user references like \"~user\".
+See <lisp/eshell/em-dirs.el>."
+  (unwind-protect
+      (with-temp-eshell
+       (cl-letf (((symbol-function 'eshell-read-user-names)
+                  (lambda () (setq eshell-user-names '((1234 . "user"))))))
+         ;; FIXME: Should this really add a space at the end?
+         (should (equal (eshell-insert-and-complete "echo ~us")
+                        "echo ~user/ "))))
+    ;; Clear the cached user names we set above.
+    (setq eshell-user-names nil)))
+
+;;; em-cmpl-tests.el ends here
diff --git a/test/lisp/eshell/esh-util-tests.el 
b/test/lisp/eshell/esh-util-tests.el
index afaf1b77f2b..ed841e96c7e 100644
--- a/test/lisp/eshell/esh-util-tests.el
+++ b/test/lisp/eshell/esh-util-tests.el
@@ -54,4 +54,69 @@
   "Test that `eshell-stringify' correctly stringifies complex objects."
   (should (equal (eshell-stringify (list 'quote 'hello)) "'hello")))
 
+(ert-deftest esh-util-test/eshell-convert-to-number/integer ()
+  "Test that `eshell-convert-to-number' correctly converts integers."
+  (should (equal (eshell-convert-to-number "123") 123))
+  (should (equal (eshell-convert-to-number "-123") -123))
+  ;; These are technially integers, since Emacs Lisp requires at least
+  ;; one digit after the "." to be a float:
+  (should (equal (eshell-convert-to-number "123.") 123))
+  (should (equal (eshell-convert-to-number "-123.") -123)))
+
+(ert-deftest esh-util-test/eshell-convert-to-number/floating-point ()
+  "Test that `eshell-convert-to-number' correctly converts floats."
+  (should (equal (eshell-convert-to-number "1.23") 1.23))
+  (should (equal (eshell-convert-to-number "-1.23") -1.23))
+  (should (equal (eshell-convert-to-number ".1") 0.1))
+  (should (equal (eshell-convert-to-number "-.1") -0.1)))
+
+(ert-deftest esh-util-test/eshell-convert-to-number/floating-point-exponent ()
+  "Test that `eshell-convert-to-number' correctly converts exponent notation."
+  ;; Positive exponent:
+  (dolist (exp '("e2" "e+2" "E2" "E+2"))
+    (should (equal (eshell-convert-to-number (concat "123" exp)) 12300.0))
+    (should (equal (eshell-convert-to-number (concat "-123" exp)) -12300.0))
+    (should (equal (eshell-convert-to-number (concat "1.23" exp)) 123.0))
+    (should (equal (eshell-convert-to-number (concat "-1.23" exp)) -123.0))
+    (should (equal (eshell-convert-to-number (concat "1." exp)) 100.0))
+    (should (equal (eshell-convert-to-number (concat "-1." exp)) -100.0))
+    (should (equal (eshell-convert-to-number (concat ".1" exp)) 10.0))
+    (should (equal (eshell-convert-to-number (concat "-.1" exp)) -10.0)))
+  ;; Negative exponent:
+  (dolist (exp '("e-2" "E-2"))
+    (should (equal (eshell-convert-to-number (concat "123" exp)) 1.23))
+    (should (equal (eshell-convert-to-number (concat "-123" exp)) -1.23))
+    (should (equal (eshell-convert-to-number (concat "1.23" exp)) 0.0123))
+    (should (equal (eshell-convert-to-number (concat "-1.23" exp)) -0.0123))
+    (should (equal (eshell-convert-to-number (concat "1." exp)) 0.01))
+    (should (equal (eshell-convert-to-number (concat "-1." exp)) -0.01))
+    (should (equal (eshell-convert-to-number (concat ".1" exp)) 0.001))
+    (should (equal (eshell-convert-to-number (concat "-.1" exp)) -0.001))))
+
+(ert-deftest esh-util-test/eshell-convert-to-number/floating-point/infinite ()
+  "Test that `eshell-convert-to-number' correctly converts infinite floats."
+  (should (equal (eshell-convert-to-number "1.0e+INF") 1.0e+INF))
+  (should (equal (eshell-convert-to-number "2.e+INF") 1.0e+INF))
+  (should (equal (eshell-convert-to-number "-1.0e+INF") -1.0e+INF))
+  (should (equal (eshell-convert-to-number "-2.e+INF") -1.0e+INF)))
+
+(ert-deftest esh-util-test/eshell-convert-to-number/floating-point/nan ()
+  "Test that `eshell-convert-to-number' correctly converts NaNs."
+  (should (equal (eshell-convert-to-number "1.0e+NaN") 1.0e+NaN))
+  (should (equal (eshell-convert-to-number "2.e+NaN") 2.0e+NaN))
+  (should (equal (eshell-convert-to-number "-1.0e+NaN") -1.0e+NaN))
+  (should (equal (eshell-convert-to-number "-2.e+NaN") -2.0e+NaN)))
+
+(ert-deftest esh-util-test/eshell-convert-to-number/non-numeric ()
+  "Test that `eshell-convert-to-number' does nothing to non-numeric values."
+  (should (equal (eshell-convert-to-number "foo") "foo"))
+  (should (equal (eshell-convert-to-number "") ""))
+  (should (equal (eshell-convert-to-number "123foo") "123foo")))
+
+(ert-deftest esh-util-test/eshell-convert-to-number/no-convert ()
+  "Test that `eshell-convert-to-number' does nothing when disabled."
+  (let ((eshell-convert-numeric-arguments nil))
+    (should (equal (eshell-convert-to-number "123") "123"))
+    (should (equal (eshell-convert-to-number "1.23") "1.23"))))
+
 ;;; esh-util-tests.el ends here
diff --git a/test/lisp/eshell/esh-var-tests.el 
b/test/lisp/eshell/esh-var-tests.el
index 12412d13640..6767d9289f9 100644
--- a/test/lisp/eshell/esh-var-tests.el
+++ b/test/lisp/eshell/esh-var-tests.el
@@ -72,52 +72,89 @@
     (eshell-command-result-equal "echo a$'eshell-test-value'z"
                                  '("a1" 2 "3z"))))
 
-(ert-deftest esh-var-test/interp-var-indices ()
-  "Interpolate list variable with indices"
-  (let ((eshell-test-value '("zero" "one" "two" "three" "four")))
+(defun esh-var-test/interp-var-indices (function &optional range-function)
+  "Test interpolation of an indexable value with indices.
+FUNCTION is a function that takes a list of elements and returns
+the object to test.
+
+RANGE-FUNCTION is a function that takes a list of elements and
+returns the expected result of an index range for the object; if
+nil, use FUNCTION instead."
+  (let ((eshell-test-value
+         (funcall function '("zero" "one" "two" "three" "four")))
+        (range-function (or range-function function)))
+    ;; Positive indices
     (eshell-command-result-equal "echo $eshell-test-value[0]"
                                  "zero")
     (eshell-command-result-equal "echo $eshell-test-value[0 2]"
                                  '("zero" "two"))
     (eshell-command-result-equal "echo $eshell-test-value[0 2 4]"
-                                 '("zero" "two" "four"))))
-
-(ert-deftest esh-var-test/interp-var-indices-subcommand ()
-  "Interpolate list variable with subcommand expansion for indices."
-  (skip-unless (executable-find "echo"))
-  (let ((eshell-test-value '("zero" "one" "two" "three" "four")))
+                                 '("zero" "two" "four"))
+    ;; Negative indices
+    (eshell-command-result-equal "echo $eshell-test-value[-1]"
+                                 "four")
+    (eshell-command-result-equal "echo $eshell-test-value[-1 -3]"
+                                 '("four" "two"))
+    ;; Index ranges
     (eshell-command-result-equal
-     "echo $eshell-test-value[${*echo 0}]"
-     "zero")
+     "echo $eshell-test-value[1..4]"
+     (funcall range-function '("one" "two" "three")))
     (eshell-command-result-equal
-     "echo $eshell-test-value[${*echo 0} ${*echo 2}]"
-     '("zero" "two"))))
+     "echo $eshell-test-value[..2]"
+     (funcall range-function '("zero" "one")))
+    (eshell-command-result-equal
+     "echo $eshell-test-value[-2..]"
+     (funcall range-function '("three" "four")))
+    (eshell-command-result-equal
+     "echo $eshell-test-value[..]"
+     (funcall range-function '("zero" "one" "two" "three" "four")))
+    (eshell-command-result-equal
+     "echo $eshell-test-value[1..4 -2..]"
+     (list (funcall range-function '("one" "two" "three"))
+           (funcall range-function '("three" "four"))))))
+
+(ert-deftest esh-var-test/interp-var-indices/list ()
+  "Interpolate list variable with indices."
+  (esh-var-test/interp-var-indices #'identity))
+
+(ert-deftest esh-var-test/interp-var-indices/vector ()
+  "Interpolate vector variable with indices."
+  (esh-var-test/interp-var-indices #'vconcat))
 
-(ert-deftest esh-var-test/interp-var-split-indices ()
+(ert-deftest esh-var-test/interp-var-indices/ring ()
+  "Interpolate ring variable with indices."
+  (esh-var-test/interp-var-indices #'ring-convert-sequence-to-ring))
+
+(ert-deftest esh-var-test/interp-var-indices/split ()
   "Interpolate string variable with indices."
-  (let ((eshell-test-value "zero one two three four"))
-    (eshell-command-result-equal "echo $eshell-test-value[0]"
-                                 "zero")
-    (eshell-command-result-equal "echo $eshell-test-value[0 2]"
-                                 '("zero" "two"))
-    (eshell-command-result-equal "echo $eshell-test-value[0 2 4]"
-                                 '("zero" "two" "four"))))
+  (esh-var-test/interp-var-indices
+   (lambda (values) (string-join values " "))
+   #'identity))
 
 (ert-deftest esh-var-test/interp-var-string-split-indices ()
   "Interpolate string variable with string splitter and indices."
+  ;; Test using punctuation as a delimiter.
   (let ((eshell-test-value "zero:one:two:three:four"))
     (eshell-command-result-equal "echo $eshell-test-value[: 0]"
                                  "zero")
     (eshell-command-result-equal "echo $eshell-test-value[: 0 2]"
                                  '("zero" "two")))
+  ;; Test using a letter as a delimiter.
   (let ((eshell-test-value "zeroXoneXtwoXthreeXfour"))
     (eshell-command-result-equal "echo $eshell-test-value[X 0]"
                                  "zero")
     (eshell-command-result-equal "echo $eshell-test-value[X 0 2]"
+                                 '("zero" "two")))
+  ;; Test using a number as a delimiter.
+  (let ((eshell-test-value "zero0one0two0three0four"))
+    (eshell-command-result-equal "echo $eshell-test-value[\"0\" 0]"
+                                 "zero")
+    (eshell-command-result-equal "echo $eshell-test-value[\"0\" 0 2]"
                                  '("zero" "two"))))
 
 (ert-deftest esh-var-test/interp-var-regexp-split-indices ()
   "Interpolate string variable with regexp splitter and indices."
+  ;; Test using a regexp as a delimiter.
   (let ((eshell-test-value "zero:one!two:three!four"))
     (eshell-command-result-equal "echo $eshell-test-value['[:!]' 0]"
                                  "zero")
@@ -126,15 +163,34 @@
     (eshell-command-result-equal "echo $eshell-test-value[\"[:!]\" 0]"
                                  "zero")
     (eshell-command-result-equal "echo $eshell-test-value[\"[:!]\" 0 2]"
+                                 '("zero" "two")))
+  ;; Test using a regexp that looks like range syntax as a delimiter.
+  (let ((eshell-test-value "zero0..0one0..0two0..0three0..0four"))
+    (eshell-command-result-equal "echo $eshell-test-value[\"0..0\" 0]"
+                                 "zero")
+    (eshell-command-result-equal "echo $eshell-test-value[\"0..0\" 0 2]"
                                  '("zero" "two"))))
 
 (ert-deftest esh-var-test/interp-var-assoc ()
   "Interpolate alist variable with index."
-  (let ((eshell-test-value '(("foo" . 1) (bar . 2))))
+  (let ((eshell-test-value '(("foo" . 1) (bar . 2) ("3" . "three"))))
     (eshell-command-result-equal "echo $eshell-test-value[foo]"
                                  1)
     (eshell-command-result-equal "echo $eshell-test-value[#'bar]"
-                                 2)))
+                                 2)
+    (eshell-command-result-equal "echo $eshell-test-value[\"3\"]"
+                                 "three")))
+
+(ert-deftest esh-var-test/interp-var-indices-subcommand ()
+  "Interpolate list variable with subcommand expansion for indices."
+  (skip-unless (executable-find "echo"))
+  (let ((eshell-test-value '("zero" "one" "two" "three" "four")))
+    (eshell-command-result-equal
+     "echo $eshell-test-value[${*echo 0}]"
+     "zero")
+    (eshell-command-result-equal
+     "echo $eshell-test-value[${*echo 0} ${*echo 2}]"
+     '("zero" "two"))))
 
 (ert-deftest esh-var-test/interp-var-length-list ()
   "Interpolate length of list variable."
diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el
index 59e160c9d71..cc93970be28 100644
--- a/test/lisp/net/tramp-tests.el
+++ b/test/lisp/net/tramp-tests.el
@@ -4923,6 +4923,9 @@ This tests also `make-symbolic-link', `file-truename' and 
`add-name-to-file'."
                (should (processp proc))
                (should (equal (process-status proc) 'run))
                (should (equal (process-get proc 'remote-command) command))
+               ;; Give the pipe process a chance to start.
+               (when (memq process-connection-type '(nil pipe))
+                 (sit-for 0.1 'nodisp))
                (process-send-string proc "foo\r\n")
                (process-send-eof proc)
                ;; Read output.
@@ -5194,7 +5197,7 @@ If UNSTABLE is non-nil, the test is tagged as 
`:unstable'."
          ;; `process-connection-type' is taken when
          ;; `:connection-type' is nil.
          (dolist (process-connection-type
-                  (unless connection-type '(nil pipe t pty)))
+                  (if connection-type '(nil pipe t pty) '(nil)))
            (unwind-protect
                (with-temp-buffer
                  (setq command '("hexdump" "-v" "-e" "/1 \"%02X\n\"")
@@ -5210,6 +5213,10 @@ If UNSTABLE is non-nil, the test is tagged as 
`:unstable'."
                  (should (processp proc))
                  (should (equal (process-status proc) 'run))
                  (should (equal (process-get proc 'remote-command) command))
+                 ;; Give the pipe process a chance to start.
+                 (when (or (eq connection-type 'pipe)
+                           (memq process-connection-type '(nil pipe)))
+                   (sit-for 0.1 'nodisp))
                  (process-send-string proc "foo\r\n")
                  (process-send-eof proc)
                  ;; Read output.
@@ -7488,7 +7495,7 @@ process sentinels.  They shall not disturb each other."
          ert-remote-temporary-file-directory)))
     (should
      (string-match-p
-      (rx "Tramp loaded: t" (+ (any "\n\r")))
+      (rx "Tramp loaded: t" (+ (any "\r\n")))
       (shell-command-to-string
        (format
        "%s -batch -Q -L %s --eval %s"
@@ -7516,9 +7523,9 @@ process sentinels.  They shall not disturb each other."
       (should
        (string-match-p
        (rx
-        "Tramp loaded: nil" (+ (any "\n\r"))
-        "Tramp loaded: nil" (+ (any "\n\r"))
-        "Tramp loaded: " (literal (symbol-name tm)) (+ (any "\n\r")))
+        "Tramp loaded: nil" (+ (any "\r\n"))
+        "Tramp loaded: nil" (+ (any "\r\n"))
+        "Tramp loaded: " (literal (symbol-name tm)) (+ (any "\r\n")))
        (shell-command-to-string
         (format
          "%s -batch -Q -L %s --eval %s"
diff --git a/test/lisp/progmodes/c-ts-mode-resources/indent-bsd.erts 
b/test/lisp/progmodes/c-ts-mode-resources/indent-bsd.erts
index 07698077ffc..ba4f854baf8 100644
--- a/test/lisp/progmodes/c-ts-mode-resources/indent-bsd.erts
+++ b/test/lisp/progmodes/c-ts-mode-resources/indent-bsd.erts
@@ -1,9 +1,9 @@
 Code:
   (lambda ()
-    (setq indent-tabs-mode nil)
-    (setq c-ts-mode-indent-offset 2)
-    (setq c-ts-mode-indent-style 'bsd)
     (c-ts-mode)
+    (setq-local indent-tabs-mode nil)
+    (setq-local c-ts-mode-indent-offset 2)
+    (c-ts-mode-set-local-style 'bsd)
     (indent-region (point-min) (point-max)))
 
 Point-Char: |
diff --git a/test/lisp/progmodes/c-ts-mode-resources/indent.erts 
b/test/lisp/progmodes/c-ts-mode-resources/indent.erts
index 67654404a77..058c6e9099c 100644
--- a/test/lisp/progmodes/c-ts-mode-resources/indent.erts
+++ b/test/lisp/progmodes/c-ts-mode-resources/indent.erts
@@ -1,9 +1,9 @@
 Code:
   (lambda ()
-    (setq indent-tabs-mode nil)
-    (setq c-ts-mode-indent-offset 2)
-    (setq c-ts-mode-indent-style 'gnu)
     (c-ts-mode)
+    (setq-local indent-tabs-mode nil)
+    (setq-local c-ts-mode-indent-offset 2)
+    (c-ts-mode-set-local-style 'gnu)
     (indent-region (point-min) (point-max)))
 
 Point-Char: |
@@ -114,7 +114,9 @@ int main() {
       {
         puts ("Hello");
       }
-  for (int i=0; i<5; i++)
+  for (int i=0;
+       i<5;
+       i++)
     if (true)
       {
         puts ("Hello");
@@ -133,30 +135,6 @@ int main() {
 }
 =-=-=
 
-Name: Bracket-less Block-Statement (Linux Style) (bug#61026)
-
-=-=-=
-int main() {
-  while (true)
-    if (true) {
-      puts ("Hello");
-    }
-  for (int i=0; i<5; i++)
-    if (true) {
-      puts ("Hello");
-    }
-  do
-    if (true) {
-      puts ("Hello");
-    }
-  while (true);
-  if (true)
-    if (true) {
-      puts ("Hello");
-    }
-}
-=-=-=
-
 Name: Multiline Parameter List (bug#60398)
 
 =-=
@@ -215,10 +193,10 @@ line 2
 
 Code:
   (lambda ()
-    (setq indent-tabs-mode nil)
-    (setq c-ts-mode-indent-offset 8)
-    (setq c-ts-mode-indent-style 'linux)
     (c-ts-mode)
+    (setq-local indent-tabs-mode nil)
+    (setq-local c-ts-mode-indent-offset 8)
+    (c-ts-mode-set-local-style 'linux)
     (indent-region (point-min) (point-max)))
 
 Name: Labels (Linux Style)
@@ -240,3 +218,29 @@ label:
         }
 }
 =-=-=
+
+Name: Bracket-less Block-Statement (Linux Style) (bug#61026)
+
+=-=-=
+int main() {
+  while (true)
+    if (true) {
+      puts ("Hello");
+    }
+  for (int i=0;
+       i<5;
+       i++)
+    if (true) {
+      puts ("Hello");
+    }
+  do
+    if (true) {
+      puts ("Hello");
+    }
+  while (true);
+  if (true)
+    if (true) {
+      puts ("Hello");
+    }
+}
+=-=-=
diff --git a/test/lisp/progmodes/java-ts-mode-resources/indent.erts 
b/test/lisp/progmodes/java-ts-mode-resources/indent.erts
index e59d5fed8e8..c8e0ac71708 100644
--- a/test/lisp/progmodes/java-ts-mode-resources/indent.erts
+++ b/test/lisp/progmodes/java-ts-mode-resources/indent.erts
@@ -42,3 +42,12 @@ if (x) {
   return;
 }
 =-=-=
+
+Name: Field declaration without access modifier (bug#61115)
+
+=-=
+public class T {
+  @Autowired
+  String a;
+}
+=-=-=
diff --git a/test/lisp/progmodes/project-tests.el 
b/test/lisp/progmodes/project-tests.el
index aea0666629d..5a206b67db1 100644
--- a/test/lisp/progmodes/project-tests.el
+++ b/test/lisp/progmodes/project-tests.el
@@ -152,4 +152,14 @@ When `project-ignores' includes a name matching project 
dir."
     (should (equal '(".dir-locals.el" "foo")
                    (mapcar #'file-name-nondirectory (project-files 
project))))))
 
+(ert-deftest project-vc-nonexistent-directory-no-error ()
+  "Check that is doesn't error out when the current dir does not exist."
+  (skip-unless (eq (vc-responsible-backend default-directory) 'Git))
+  (let* ((dir (expand-file-name "foo-456/bar/" (ert-resource-directory)))
+         (_ (vc-file-clearprops dir))
+         (project-vc-extra-root-markers '(".dir-locals.el"))
+         (project (project-current nil dir)))
+    (should-not (null project))
+    (should (string-match-p "/test/lisp/progmodes/project-resources/\\'" 
(project-root project)))))
+
 ;;; project-tests.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]